标签: lto

连接器如何应对快速返回的功能?

在C中,如果我有一个看起来像的函数调用

// main.c
...
do_work_on_object(object, arg1, arg2);
...

// object.c
void do_work_on_object(struct object_t *object, int arg1, int arg2)
{
  if(object == NULL)
  {
    return;
  }
  // do lots of work
}
Run Code Online (Sandbox Code Playgroud)

那么编译器会在main.o中生成很多东西来保存状态,传递参数(在这种情况下希望在寄存器中),以及恢复状态.

但是,在链接时可以观察到arg1和arg2没有用在快速返回路径中,因此清理和状态恢复可以短路.链接器是否会自动执行此类操作,或者是否需要启用链接时优化(LTO)才能使此类工作正常工作?

(是的,我可以检查反汇编代码,但我对编译器和链接器的行为以及多种体系结构感兴趣,所以希望从别人的经验中学习.)

假设分析显示此函数调用值得优化,我们是否应该期望以下代码明显更快(例如,无需使用LTO)?

// main.c
...
if(object != NULL)
{
  do_work_on_object(object, arg1, arg2);
}
...

// object.c
void do_work_on_object(struct object_t *object, int arg1, int arg2)
{
  assert(object != NULL) // generates no code in release build
  // do lots of work
}
Run Code Online (Sandbox Code Playgroud)

c linker micro-optimization lto

6
推荐指数
1
解决办法
98
查看次数

binutils和gcc与LTO

我将binutils-2.25.1安装到/usr/local/binutils-2.25.1,配置了

../configure --prefix=/usr/local/binutils-2.25.1 --enable-plugins --enable-gold --disable-werror
Run Code Online (Sandbox Code Playgroud)

我想构建RPM包 - 使用LTO支持的gcc,它使用来自/usr/local/binutils-2.25.1的链接器ld.

我尝试:

Summary: The GNU Compiler Collection
Name: gcc-custom
Version: 4.9.3
%define full_name gcc-%{version}
%define binutils_path /usr/local/binutils-2.25.1
Release: 0
...
Requires(post): /sbin/ldconfig
Requires(postun): /sbin/ldconfig

%description

%prep
%setup -q -a0 -n %{full_name}

%build
AR=%{binutils_path}/bin/ar NM=%{binutils_path}/bin/nm RANLIB=@%{binutils_path}/bin/ranlib ./configure \
    --prefix=/usr/local/%{full_name} \
    --disable-multilib \
    --enable-languages=c,c++ \
    --enable-lto \
    --enable-linker-build-id \
    --enable-plugin \
    --with-ld=%{binutils_path}/bin/ld \
    --with-plugin-ld=%{binutils_path}/bin/ld \
    --with-as=%{binutils_path}/bin/as
make

%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT

%post -p /sbin/ldconfig

%postun -p /sbin/ldconfig

%clean …
Run Code Online (Sandbox Code Playgroud)

c++ gcc binutils lto

6
推荐指数
0
解决办法
2421
查看次数

抑制具有灵活数组的struct的-Wlto-type-mismatch警告

我正在使用-Wlto-type-mismatch-Werror设置gcc编译(为了项目的其余部分).我有extern struct一个灵活的阵列,引发lto-type-mismatch警告/错误.

这是从一个例子中提取的代码:

HH:

typedef struct {
  int i;
  int ints[];
} struct_t;
Run Code Online (Sandbox Code Playgroud)

AC:

#include "h.h"

extern struct_t my_struct;

int main() {  // just here to avoid optimizing away the decls
  return my_struct.ints[0];
}
Run Code Online (Sandbox Code Playgroud)

公元前:

#include "h.h"

struct_t my_struct = {
  20,
  {
    1,
    2,
  },
};
Run Code Online (Sandbox Code Playgroud)

编译(在这里使用arm gcc,但它也使用原生gcc失败)

$ arm-none-eabi-gcc -flto -Wlto-type-mismatch -Werror a.c b.c -o foo
a.c:3:17: error: size of 'my_struct' differ from the size of original declaration [-Werror=lto-type-mismatch]
 extern …
Run Code Online (Sandbox Code Playgroud)

gcc lto

6
推荐指数
1
解决办法
850
查看次数

gcc 有薄 lto 吗?

Clang 允许使用精简 lto 来加快编译时间,同时仍然保留使用 lto 和选项的大部分优点-flto=thin。gcc 是否有相当于 clang 的瘦 lto 的功能?

gcc clang lto

6
推荐指数
1
解决办法
3565
查看次数

为什么我用 -LTO 构建的 C++ 二进制文件如此之大?

我正在 Mac 上编译一些二进制文件,但是使用更新的编译器编译后的大小变得很大(从之前的 ~5MB 增加到 ~20MB)。我认为这与之前未激活的 LTO(链接时间优化)有关。我没有在 linux 上观察到这个文件膨胀。

在玩弄之后strip(实际上没有减少大小,尽管尝试基于 Xcode 的标志-S -x并且也没有标志,以及 GNU libtools strip 由 homebrew binutils 配方提供的标志-s,所有这些似乎都具有相同的效果)我找到了这个工具:https ://github.com/google/bloaty Bloaty McBloated,在我的二进制文件上运行时,它会产生以下输出:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  53.9%  9.72Mi  53.8%  9.72Mi    __GNU_LTO,__wrapper_sects
  32.5%  5.86Mi  32.4%  5.86Mi    __GNU_DWARF_LTO,__debug_info
   6.2%  1.11Mi   6.2%  1.11Mi    __TEXT,__text
   2.2%   403Ki   2.2%   403Ki    __TEXT,__eh_frame
   1.6%   298Ki   1.6%   298Ki    __GNU_LTO,__wrapper_names
   1.0%   177Ki   1.0%   177Ki    Export Info
   0.7%   131Ki   0.7%   131Ki    Weak Binding Info
   0.4%  77.0Ki   0.4%  77.0Ki    __GNU_DWARF_LTO,__debug_str
   0.4% …
Run Code Online (Sandbox Code Playgroud)

c++ macos compilation lto

6
推荐指数
1
解决办法
370
查看次数

如何将 PGO + LTO 优化与 GCC 结合使用

我最近一直在研究 PGO 和 LTO 如何显着优化程序速度(有人说大约 20%)。我目前只是用 C 语言编程,并在 Windows 中使用 GTK+ 构建 GUI(通过 GCC 编译所有内容),并且仅使用 -O2 进行优化。

我一直在阅读并使用标志进行编译

gcc -Wall -g -mwindows -O3 -fprofile-generate -flto example.c -o example.exe `pkg-config --cflags --libs gtk+-3.0`
Run Code Online (Sandbox Code Playgroud)

创建了 .gcno 和 .gcda 文件,然后运行编译后的 .exe 多次,然后再次重新编译相同的 .c 文件,但将“-fprofile-generate”替换为“-fprofile-use”?(同时确保所有这些文件位于同一文件夹/目录中,并为第二次编译的 .exe 使用不同的名称)

gcc -Wall -g -mwindows -O3 -fprofile-use -flto example.c -o program.exe `pkg-config --cflags --libs gtk+-3.0`
Run Code Online (Sandbox Code Playgroud)

或者您是否以某种方式使用 .gcno/.gcda 文件?另请阅读有关使用“基准”的内容。

问题:

在GCC中使用它的步骤是什么?(分步指南会有所帮助:)

c optimization gcc lto pgo

5
推荐指数
0
解决办法
2664
查看次数

Clang、GCC 和 LTO 之间的互操作性

我知道 Clang 和 GCC 或多或少是兼容的 C/C++ 编译器,只要处理好架构标志、预定义和链接正确的库之类的事情。使用一个编译器创建库并将它们与另一个编译器创建的对象链接实际上非常简单(至少在 x86 上)。

这是一个小测试项目,正是这样做的: https://gitlab.com/higaski/Interoperability

但是我想知道链接时间优化(LTO)是否可以跨编译器工作?我知道 LTO 需要某种形式的中间表示,例如 LLVM 位码或 GCC GIMPLE,但也许有一个工作流程可以同时利用它们?

c++ gcc interop clang lto

5
推荐指数
1
解决办法
1104
查看次数

LTO 模式下 ARM 的 GCC 8 正在删除中断处理程序和弱函数 - 如何防止它?

我的目标设备是基于 EFM32 Cortex-M3 的设备。我的工具链是官方的 ARM GNU 工具链 gcc-arm-none-eabi-8-2018-q4-major。

在没有 LTO 的情况下一切正常,但为了使 LTO 工作,我必须用-fno-lto. 我想摆脱这种解决方法。

问题是,每个中断处理程序都从最终的二进制文件中删除。(我正在检查arm-none-eabi-nm --print-size --size-sort --radix=d -C -n file.out)这会导致二进制崩溃。

在谷歌搜索类似问题后进行更深入的挖掘:

来自startup_efm32gg.c定义默认中断处理程序的示例代码如下:

void DMA_IRQHandler(void) __attribute__ ((weak, alias("Default_Handler")));
/* many other interrupts */
void Default_Handler(void) { while (1); }
Run Code Online (Sandbox Code Playgroud)

常规中断处理程序定义也会发生同样的问题(例如,没有别名且不弱)

这可能是相关的,但似乎弱符号在 LTO 模式下也以同样的方式运行不正常。

提前感谢您的任何想法!

编辑:有关完整解决方案,请参阅我对标记答案的回复!

c gcc arm lto

5
推荐指数
1
解决办法
1306
查看次数

使用“-lto-embed-bitcode”提取嵌入的 LLVM 位码

目标:从 ELF 二进制文件中提取完整程序(合并)的 LTO 后位码。

该程序恰好是用 Rust 编写的,但我认为这不是一个关键的细节。

我可以.llvmbc使用以下 Cargo 调用将 Rust 程序编译为 ELF 二进制文件,其中包含一个部分:

RUSTFLAGS="-C linker_plugin_lto -C linker=clang -C link-arg=-fuse-ld=lld -C link-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized" \
    cargo build --release
Run Code Online (Sandbox Code Playgroud)

然后我就可以用来readelf -S | grep llvmbc验证该部分是否存在。确实如此。高超!

我现在想提取完整程序的 LTO 后位码并反汇编它:

$ objcopy target/release/world --dump-section .llvmbc=llvm.bc
$ llvm-dis llvm.bc
LLVM ERROR: Invalid encoding
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llvm-dis llvm.bc
 #0 0x000055c06f7ae78c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1b578c)
 #1 0x000055c06f7ac6e4 llvm::sys::RunSignalHandlers() (/home/vext01/research/yorick/llvm-project/inst/bin/llvm-dis+0x1b36e4)
 #2 …
Run Code Online (Sandbox Code Playgroud)

llvm rust lto lld bitcode

5
推荐指数
0
解决办法
1087
查看次数

不需要在头文件中定义函数进行内联吗?

为了使编译器内联函数调用,它需要具有完整的定义。如果头文件中没有定义该函数,则编译器只有声明,即使想内联该函数也无法内联。

因此,我通常定义一些短函数,我认为编译器可能希望将其内联到头文件中。

通过整个程序优化(/LTCG/GL),是否不再需要在头文件中定义函数来允许它们内联?

除了在某些情况下使用模板之外,是否还有其他原因在头文件中定义函数?

c++ inlining lto

5
推荐指数
1
解决办法
302
查看次数

标签 统计

lto ×10

gcc ×6

c++ ×4

c ×3

clang ×2

arm ×1

binutils ×1

bitcode ×1

compilation ×1

inlining ×1

interop ×1

linker ×1

lld ×1

llvm ×1

macos ×1

micro-optimization ×1

optimization ×1

pgo ×1

rust ×1