如何要求 Clang++ 在 -O3 优化期间不缓存函数结果?

How to ask Clang++ not to cache function result during -O3 optimization?

这是我的代码:

int foo(int x) {
  return x + 1; // I have more complex code here
}
int main() {
  int s = 0;
  for (int i = 0; i < 1000000; ++i) {
    s += foo(42);
  }
}

如果没有 -O3,这段代码可以工作几分钟。使用 -O3 它 returns 立即得到相同的结果。我相信 Clang++ 缓存 foo(42) 的值(它是一个纯函数)并且不会调用它一百万次。我怎样才能指示它不要对这个特定的函数调用应用这个特定的优化?

出于好奇,您能否分享一下为什么要禁用该优化?

总之,关于你的问题:

在您的示例代码中,s 在循环后永远不会被读取,因此编译器会丢弃整个循环。所以我们假设在循环之后使用s

我不知道有任何编译指示或编译器选项可以禁用特定代码段中的特定优化。

是否可以更改代码? 为了以可移植的方式防止这种优化,您可以寻找一种创造性的方法来计算函数调用参数,使编译器不再能够将参数视为常量。当然,这里的挑战是实际使用一种不依赖于未定义行为并且不能被更新的编译器版本“智胜”的技巧。

请参阅下面的注释示例。

  • 亲:你使用的技巧只使用你可以选择性应用的语言
  • con:你在每次循环迭代中都获得了额外的内存访问;但是,大部分时间 CPU 缓存都会满足访问

我使用 clang++ -O3 -S 验证了为您的特定示例生成的程序集。编译器现在生成您的循环并且不再缓存结果。但是,该函数被内联。如果你也想防止这种情况,你可以用 __attribute__((noinline)) 声明 foo,例如。

int foo(int x) {
  return x + 1; // I have more complex code here
}

volatile int dummy = 0; // initialized to 0 and never changed

int main() {
  int s = 0;
  for (int i = 0; i < 1000000; ++i) {
    // Because of the volatile variable, the compiler is forced to assume
    // that the function call argument is different for each loop
    // iteration and it is no longer able to use a cached result.
    s += foo(42 + dummy);
  }
}