gpt4 book ai didi

c++ - __attribute((const)) 的不一致 gcc 行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:46 26 4
gpt4 key购买 nike

我在 gcc 中遇到了一个关于用 __attribute((const)) 标记的运算符和函数的非常奇怪的行为。逻辑和算术运算符导致不同的优化,我不明白为什么。

这并不是真正的错误,因为 __attribute((const)) 只是一个提示,不能保证其效果,但这仍然非常令人惊讶。谁有任何解释?

这是代码。所以我定义了一个 __attribute((const)) 函数:

int f(int & counter) __attribute((const));
int f(int & counter) {
++counter;
return 0;
}

然后我定义了一个运算符(operator)测试宏。这是通过宏而不是模板/仿函数完成的,以向编译器呈现简单代码并简化优化:

int global = 0; // forces results to be computed

#define TestOp(OP) \
{ \
int n = 0; \
global += (f(n) OP f(n)); \
std::cout << "op" #OP " calls f " << n << " times" << std::endl; \
}

最后,我按如下方式测试了不同的运算符。注释与 g++-4.8 -std=c++11 -O2 -Wall -pedantic 的输出相匹配 -O3-Ofast

int main() {
// all calls optimized away
TestOp(^) // 0
TestOp(-) // 0
// one call is optimized away
TestOp(|) // 1
TestOp(&) // 1
TestOp(||) // 1
TestOp(&&) // 1
// no optimization
TestOp(+) // 2
TestOp(*) // 2

return global;
}

我的问题是:为什么算术运算符会产生两次调用?为什么不能将 f()+f() 优化为 2*f() ?有没有办法帮助/强制这种优化?起初我认为乘法可能更昂贵,但我尝试使用 f()+....+f() 并且 10 个加法仍然没有减少到 10*f() 。此外,由于它是 int 算法,因此操作顺序无关紧要(与 float 相反)。

我还检查了 asm,但没有帮助:所有的整数似乎都是在编译时预先计算的。

最佳答案

编译器不信任你。由于您有一个引用参数,编译器似乎不信任您的 const 属性 - const 函数应该只查看通过参数传递的值(而不是引用或取消引用指针)。

另一种测试方法是在单独的编译单元中分解 const 函数:

测试1.cpp:

#include <stdio.h>
int global = 0; // forces results to be computed

int f(int i) __attribute((const));
void print_count(void);

#define TestOp(OP) \
{ \
int n = 0; \
global += (f(n) OP f(n)); \
printf("op %s ", #OP);\
print_count();\
}

int main() {
// all calls optimized away
TestOp(^) // 0
TestOp(-) // 0
// one call is optimized away
TestOp(|) // 1
TestOp(&) // 1
TestOp(||) // 1
TestOp(&&) // 1
// no optimization
TestOp(+) // 2
TestOp(*) // 2

return global;
}

计数器.cpp:

#include <stdio.h>
static int counter = 0;

int f(int i) {
++counter;
return 0;
}

void print_count(void)
{
printf("counter %d\n", counter);
counter = 0;
}

现在编译器发现不需要调用f(0) 直到f(0) | f(0),并且对 f(0) 的一次调用的结果被重新用于其他情况。

$ g++ -O2 -c counter.cpp && g++ -O2 -c test.cpp && g++ counter.o test.o && ./a.out
op ^ counter 0
op - counter 0
op | counter 1
op & counter 0
op || counter 0
op && counter 0
op + counter 0
op * counter 0

关于c++ - __attribute((const)) 的不一致 gcc 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20329496/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com