首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >常数组合在优化编译器中的应用

常数组合在优化编译器中的应用
EN

Stack Overflow用户
提问于 2011-02-15 22:22:47
回答 3查看 2.5K关注 0票数 7

我有一个包含许多小内联函数的头文件。他们中的大多数碰巧都有固定的数据。由于这些函数的性能非常重要,因此它们处理常量的方式变得非常重要。AFAIK有两种方法来引用常量:

1)在一个单独的源文件中定义它们,该源文件稍后将与应用程序链接。

2)定义原地常量。

我会选择后一种方式,因为它更易于维护。但是,如果编译器不优化通过内联创建的数千个相等的常量,那么它可能会慢一些。

问题:

编译器会合并这些相同的常量吗?具体而言,将采用下列哪一种方法?

( 1)在编译单元之间合并相等的常数。

( 2)连接模块(整个程序或库)中的等量组合。

3)将常量与任何具有相同位模式的静态常量数据组合起来,满足编译单元或整个程序的对齐要求。

我使用现代编译器(GCC4.5)。

我不是汇编程序专家,因此我自己无法用几个简单的测试来回答这个问题:)

编辑:

常量相当大(其中大多数至少有16个字节),所以编译器不能立即为它们设置值。

EDIT2:

代码示例

这个地方使用常量:

代码语言:javascript
复制
float_4 sign(float_4 a)
{
    const __attribute__((aligned(16))) float mask[4] = { //I use a macro for this line
        0x80000000, 0x80000000, 0x80000000, 0x80000000};
    const int128 mask = load(mask);
    return b_and(a, mask);
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-02-15 22:47:09

根据GCC,下面的选项可以满足您的需要:

-fmerge-常数试图在编译单元之间合并相同的常量(字符串常量和浮点常数)。如果汇编程序和链接器支持该选项,则此选项是优化编译的默认选项。使用-fno-合并常量来抑制这种行为. 已在-O、-O2、-O3、-Os级别启用。

票数 8
EN

Stack Overflow用户

发布于 2011-02-15 22:45:35

如果在头文件中定义常量,如下所示:

代码语言:javascript
复制
int const TEN = 10;
// or
enum { ELEVEN = 11 };

也就是说,在编译翻译单元( .cc源文件)时,不仅常量声明,而且定义对编译器也是可见的,然后编译器当然会在未启用优化的情况下用生成的代码中的常量值替换它。

代码语言:javascript
复制
[max@truth test]$ cat test.cc
int const TEN = 10; // definition available
extern int const TWELVE; // only declaration

int foo(int x) { return x + TEN; }
int bar(int x) { return x + TWELVE; }

[max@truth test]$ g++ -S -o - test.cc | c++filt | egrep -v " *\."
foo(int):
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -4(%rbp)
    movl    -4(%rbp), %eax
    addl    $10, %eax
    leave
    ret
bar(int):
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -4(%rbp)
    movl    TWELVE(%rip), %eax
    addl    -4(%rbp), %eax
    leave
    ret
TEN:

注意,在foo(int)中,它是如何以addl $10, %eax的形式进行加法的,即用它的值替换十个常量。另一方面,在bar(int)中,它首先执行movl TWELVE(%rip), %eax将12的值从内存加载到eax寄存器(地址将由链接器解析),然后执行添加addl -4(%rbp), %eax

优化的版本如下所示:

代码语言:javascript
复制
[max@truth test]$ g++ -O3 -S -o - test.cc | c++filt | egrep -v " *\."
foo(int):
    leal    10(%rdi), %eax
    ret
bar(int):
    movl    TWELVE(%rip), %eax
    addl    %edi, %eax
    ret
票数 2
EN

Stack Overflow用户

发布于 2011-02-15 22:50:33

我不认为你的问题有一般的答案。我只为C提供一个,C++的规则是不同的。

这在很大程度上取决于常量的类型。一个重要的类是“整数常量表达式”。它们可以在编译时确定,特别是用作“整数枚举常量”的值。你可以随时使用它。

代码语言:javascript
复制
enum { myFavoriteDimension = 55/2 };

对于这样的常量,最好的情况通常应该发生:它们是作为汇编程序直接实现的。它们甚至没有存储位置,直接写入汇编程序,您的问题甚至没有意义。

对于其他数据类型,这个问题更为微妙。尝试强制不使用"const限定变量“的地址。这可以用register关键字来完成。

代码语言:javascript
复制
register double const something = 5.7;

可能具有与上述相同的效果。

对于组合类型(structunion、数组),没有通用的答案或方法。我已经看到gcc能够完全优化小阵列(大约10个元件)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5010216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档