Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 优化编译器中的常数合并_C++_C_Gcc_Constants_Inline - Fatal编程技术网

C++ 优化编译器中的常数合并

C++ 优化编译器中的常数合并,c++,c,gcc,constants,inline,C++,C,Gcc,Constants,Inline,我有一个头文件,其中包含许多小型内联函数。他们中的大多数人碰巧有固定的数据。由于这些函数对性能至关重要,因此它们处理常量的方式变得非常重要。AFAIK引用常量有两种方法: 1) 在稍后与应用程序链接的单独源文件中定义它们 2) 在适当的位置定义常量 我会选择后一种方式,因为它更易于维护。但是,如果编译器不优化通过内联创建的数千个相等常量,则速度可能会较慢 问题: 编译器会将这些相等的常量组合起来吗?特别是,将使用以下哪种方法 1) 编译单元中相等常数的组合。 2) 跨链接模块(整个程序或库)合并

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

1) 在稍后与应用程序链接的单独源文件中定义它们

2) 在适当的位置定义常量

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

问题:

编译器会将这些相等的常量组合起来吗?特别是,将使用以下哪种方法

1) 编译单元中相等常数的组合。
2) 跨链接模块(整个程序或库)合并相等常数
3) 将常量与碰巧具有相同位模式并满足整个编译单元或整个程序的对齐要求的任何静态常量数据相结合

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

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

编辑:

这些常量相当大(大多数至少16字节),因此编译器无法使它们成为立即值

EDIT2:

代码示例

这一个使用了就地常数:

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);
}

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

int const TEN = 10;
// or
enum { ELEVEN = 11 };
[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
也就是说,编译翻译单元(一个.cc源文件)时,编译器不仅可以看到常量声明,还可以看到定义,然后,即使没有启用优化,编译器也会在生成的代码中用常量值替换它

[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十二(%rip),%eax
将十二的值从内存加载到eax寄存器(地址将由链接器解析),然后执行加法
addl-4(%rbp),%eax

优化版本如下所示:

int const TEN = 10;
// or
enum { ELEVEN = 11 };
[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
根据以下选项,您可以选择以下选项:

-F能量常数

尝试跨编译单元合并相同的常量(字符串常量和浮点常量)。 如果汇编程序和链接器支持此选项,则此选项是优化编译的默认选项。使用-fno合并常量可禁止此行为。
在-O、-O2、-O3、-Os级别启用


我不认为你的问题有一般性的答案。我只给C一个,C++的规则是不同的。 这在很大程度上取决于常量的类型。一个重要的类是“整数常量表达式”。这些可以在编译时确定,特别是用作“整数枚举常量”的值。随时使用它

enum { myFavoriteDimension = 55/2 };
对于这样的常量,最好的事情通常会发生:它们是作为汇编程序立即实现的。它们甚至没有存储位置,直接写入汇编程序,你的问题根本没有意义

对于其他数据类型,这个问题更为微妙。尝试强制执行不获取“const限定变量”的地址。这可以通过
寄存器
关键字来完成

register double const something = 5.7;
可能具有与上述相同的效果


对于组合类型(
struct
union
,数组),没有通用的答案或方法。我已经看到gcc能够完全优化小数组(10个元素左右)。

您所说的“就地定义常量”是什么意思?像
const int i=5?是的。我所说的常量是指独立于函数参数的任何数据。我不是GCC方面的专家,但大多数编译器根本不组合常量文本,除非它们是字符串文本。此外,常量文本通常作为立即值嵌入到代码中。一旦将值加载到内存变量中,就由comiler强制执行该值的常量;e、 在“因为这些函数是性能关键的,所以它们处理常量的方式变得很重要。”以及在“但是,如果编译器不优化通过内联创建的数千个相等常量,它可能会变慢。”顺便说一句,