标签: lto

lto和fat-lto-objects之间的gcc有什么区别

我试图用下一个标志编译汇编我的源代码:
1.2 -flto
. -flto -ffat-lto-objects
3.-flto -fno-fat-lto-objects

第三个提供slim了文档中编写的优化LTO代码,但我没有看到输出汇编文件在第一个和第二个之间有任何差异,为什么?

OS:linux
编译器:GCC 4.7

optimization gcc lto

11
推荐指数
1
解决办法
6104
查看次数

如何在LLVM中编写自定义的模块间通道?

我通过扩展FunctionPass类在LLVM中编写了标准的Analysis传递.一切似乎都有意义.

现在我要做的是编写几个模块间通道,即允许我一次分析多个模块的通道.一个这样的传递的目的是构建整个应用程序的调用图.另一个这样的传递的目的是我有一个关于函数调用及其参数的优化的想法.

我知道LLVM中的过程间通过,通过扩展ModulePass类,但只允许在单个模块中进行分析.

我知道LLVM中的链接时间优化(LTO),但是(a)我不太清楚这是否是我想要的,(b)我没有找到关于如何实际编写 LTO传递的示例或文档.

如何在LLVM中编写一个模块间传递,即一个可以访问应用程序中所有模块的传递?

static-analysis llvm llvm-ir lto

11
推荐指数
2
解决办法
2019
查看次数

使用flto的要求

如果我想编译我的项目-flto是否足以建立gcc --enable-gold或者我还需要构建黄金并用它替换ld?我还需要其他标志吗?即我这样做

gcc -flto one.c two.c
Run Code Online (Sandbox Code Playgroud)

gcc ld binutils lto gold-linker

11
推荐指数
1
解决办法
1万
查看次数

防止GCC LTO删除功能

我使用GCC-ARM-Embedded和FreeRTOS.FreeRTOS具有vTaskSwitchContext()仅在某些内联汇编程序代码中使用的函数.

问题是:当我使用LTO时,GCC不考虑内联汇编程序代码并认为该函数未被使用,因此将其删除.然后链接器失败,因为内联汇编程序代码中的函数调用无法解析.

我会申请,__attribute__((used))但我不想触摸FreeRTOS代码(它是由STM32CubeMX生成的).

我尝试将它放在我的代码中,但实际上GCC足够智能,不允许这个工作:

if(false)
    vTaskSwitchContext();
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉GCC在不同的源文件或通过参数,不应该删除此功能?

// file1.c
void vTaskSwitchContext( void )
{
    ...
}

// file2.c
void xPortPendSVHandler( void )
{
    __asm volatile
    (
    ...
    "   isb                                 \n"
    "   bl vTaskSwitchContext               \n"
    "   mov r0, #0                          \n"
    ...
    );
}
Run Code Online (Sandbox Code Playgroud)

c gcc ld freertos lto

10
推荐指数
2
解决办法
1495
查看次数

在 LTO 模式下从 GCC/Clang 获取汇编输出

通常,可以使用GCC 和 Clang 中的标志从源文件中获取 GCC 的优化汇编器输出-S如下例所示。

gcc -O3 -S -c -o foo.s foo.c
Run Code Online (Sandbox Code Playgroud)

但是假设我编译所有源文件-O3 -flto以启用链接时整个程序优化,并希望查看最终编译器生成的函数优化程序集,和/或查看代码在哪里/如何内联。

编译的结果是一堆.o文件,正如预期的那样,这些文件实际上是伪装成目标文件的 IR 文件。在链接可执行文件或共享库时,它们会被混合在一起,作为一个整体进行优化,然后编译成目标二进制文件。

但是如果我想要这个过程的汇编输出怎么办?也就是说,链接时优化之后、在将 IR 编译为程序集期间以及在实际程序集和链接到最终可执行文件之前产生的程序集源。

我尝试简单地向-S链接步骤添加一个标志,但这并没有真正起作用。

我知道反汇编可执行文件是可能的,甚至与源代码交错,但有时查看实际编译器生成的程序集会更好,尤其是使用-fverbose-asm.

assembly gcc clang lto

9
推荐指数
1
解决办法
415
查看次数

未定义的引用在GCC下交叉编译LTO的静态库

我试图使用GCC 4.9.2从Linux(x86_64-pc-linux-gnu)for Windows(x86_64-w64-mingw32)交叉编译应用程序.

当构建链接到静态库并且还使用链接时优化的目标时,我从链接器获取目标从库中使用的所有符号的未定义引用错误.

例如,从bar.cpp建立bar.a

int bar (void) {return 42;}
Run Code Online (Sandbox Code Playgroud)

并与foo.cpp链接

extern int bar (void);
int main (int, char**) {bar ();}
Run Code Online (Sandbox Code Playgroud)

使用命令行

x86_64-w64-mingw32-g++ -flto -o foo.o -c foo.cpp
x86_64-w64-mingw32-g++ -flto -o bar.o -c bar.cpp
x86_64-w64-mingw32-gcc-ar rc bar.a bar.o
x86_64-w64-mingw32-gcc-ranlib bar.a
x86_64-w64-mingw32-g++ -flto -fuse-linker-plugin foo.o bar.a -o foo
Run Code Online (Sandbox Code Playgroud)

导致错误

/tmp/ccc3Twsc.lto.o:foo.o:(.text+0x15): undefined reference to `bar()'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

从上面:

  • 我正在使用ar/ranlib的gcc-wrappers
  • 没有外部依赖
  • 所有文件都使用相同的选项进行编译

我尝试过使用-fuse-linker-plugin,gcc-ar vs ar,符号可见性选项,操作等的各种组合,但是如果不关闭LTO,我无法正确链接.

所有目标都在本机编译器(x86_64 Linux)下正确构建.

有什么明显的东西我在这里不见了吗?

c++ gcc mingw cross-compiling lto

8
推荐指数
1
解决办法
2096
查看次数

如何将LTO与符号版本控制相结合

我想使用符号版本控制和链接时优化(LTO)编译共享库.但是,只要我打开LTO,一些导出的符号就会消失.这是一个最小的例子:

首先定义函数fun的两个实现:

$ cat fun.c 
#include <stdio.h>

int fun1(void);
int fun2(void);

__asm__(".symver fun1,fun@v1");
int fun1() {
    printf("fun1 called\n");
    return 1;
}

__asm__(".symver fun2,fun@@v2");
int fun2() {
    printf("fun2 called\n");
    return 2;
}
Run Code Online (Sandbox Code Playgroud)

创建版本脚本以确保仅导出乐趣:

$ cat versionscript 
v1 {
    global:
        fun;
    local:
        *;
};
v2 {
    global:
        fun;
} v1;
Run Code Online (Sandbox Code Playgroud)

第一次尝试,没有LTO编译:

$ gcc -o fun.o -Wall -Wextra -O2 -fPIC -c fun.c
$ gcc -o libfun.so.1 -shared -fPIC -Wl,--version-script,versionscript fun.o
$ nm -D --with-symbol-versions libfun.so.1 | grep fun
00000000000006b0 …
Run Code Online (Sandbox Code Playgroud)

c linker gcc lto

7
推荐指数
1
解决办法
522
查看次数

替换 __aeabi_dsub 以节省空间(-flto 问题)

我试图将大量代码塞进一个相当小的 ARM 微控制器中。我已经做了尺寸优化工作的巨量已经和我到哪里,我需要加倍运算的地步,但是__aeabi_ddiv__aeabi_dadd__aeabi_dsub一些最大的功能,整个设备上。

这两个__aeabi_dadd__aeabi_dsub是尽管基本上做同样的工作〜1700 bytes每个(双打的最高层位为符号位)。两个函数都没有引用另一个。

实际上,我需要做的就是替换__aeabi_dsub为:

double __aeabi_dsub(double a, double b) {
  // flip top bit of 64 bit number (the sign bit)
  ((uint32_t*)&b)[1] ^= 0x80000000; // assume little endian
  return a + b;
}
Run Code Online (Sandbox Code Playgroud)

我会节省大约 1700 个字节 - 所以翻转第二个参数的符号,然后使用__aeabi_dadd.

我知道这可能不是 100% 与 IEEE 规范兼容,但在这个平台上,为了节省 > 1% 的可用闪存,我可以接受。

我的问题是,当我添加该函数时,链接器会抱怨undefined reference to __aeabi_dsub- 这似乎很奇怪,因为定义它的行为导致了错误。

这似乎与链接时间优化 ( -flto) 有关 - 将其关闭意味着一切正常,但它会增加 8k 的固件大小,使其不再适合可用的闪存!

那么__aeabi_dsub …

c embedded gcc arm lto

7
推荐指数
1
解决办法
667
查看次数

即使传递了 -fno-lto ,lld 也会运行 LTO

我有一个 CMake 项目,其中有几个子项目,这些子项目创建使用-flto=thin.

该项目有很多与上述库相关的测试。使用 LTO 需要花费大量时间来构建测试,因此我已禁用 LTO 进行使用-fno-lto.

但我注意到,lld即使使用-fno-lto. 如果我运行链接器,--time-trace我可以看到大部分时间都花在了 LTO 上。

我的问题是:

  1. 这是预期的吗?如果是这样,我可以假设lld只要在它链接的对象中找到 LTO 信息,就会执行 LTO。
  2. 如果没有,有没有办法禁用这种行为?添加-fno-lto到编译器似乎不起作用,并且lld没有显式禁用 LTO 的参数。
  3. 如果不是,这是一个错误吗?

更新1:

这就是我lto在 CMake 中的处理方式:

# Enable Thin LTO only on non-test targets.
if(ENABLE_LTO)
  if (IS_TEST)
    target_compile_options(${TARGET} PRIVATE -fno-lto)
    # Probably pointless.
    target_link_options(${TARGET} PRIVATE -fno-lto)
  else()
    message(STATUS "ENABLE_LTO on target ${TARGET})")
    target_compile_options(${TARGET} PRIVATE -flto=thin)
    target_link_options(${TARGET} PRIVATE -flto=thin -Wl,--thinlto-cache-dir=${CMAKE_BINARY_DIR}/lto.cache)
  endif()
endif()
Run Code Online (Sandbox Code Playgroud)

c++ clang clang++ lto lld

7
推荐指数
1
解决办法
2241
查看次数

LTO 优化全局变量

我看到 LTO 优化了某个 TU 中的一些全局对象,如果该 TU 中没有明确来自另一个 TU 的函数。

以下摘录尝试描述所涉及的关键类和文件(请注意,这仅用于演示目的,可能并不完全准确):

我有一个单例类,它维护已构造的Registrar所有类型对象的列表。Foo为了避免静态构造顺序失败,我在构造第一个 Foo 类型的对象时动态构造该对象的实例。

// Registrar.hpp
class Registrar
{
public:
  static Registrar * sRegistrar;
  std::vector<Foo *> objectList;
  Registrar() = default;
};
Run Code Online (Sandbox Code Playgroud)

接下来,我们上课了Foo。此类的实例Registrar如上所述进行注册。

// Foo.hpp
class Foo
{
public:
  Foo()
  {
    if (Registrar::sRegistrar == nullptr)
      Registrar::sRegistrar = new Registrar();

    Registrar::sRegistrar->objectList.push_back(this);
  }
};
Run Code Online (Sandbox Code Playgroud)

的实例Foo是可以从多个文件创建的全局变量。在一个这样的文件中,我们碰巧定义了另一个从其他地方调用的函数:

// file1.hpp
void someFunctionThatIsCalledExplicitly()
{
  doSomething();
}

namespace 
{
  __attribute__((used, retain))
  Foo f1;
}
Run Code Online (Sandbox Code Playgroud)

但在另一个文件中,我们只是创建了一个实例Foo

// file2.hpp …
Run Code Online (Sandbox Code Playgroud)

c++ clang lto

7
推荐指数
1
解决办法
661
查看次数