MSVS/C++:不会被优化掉的最快的总是假的条件?

Posted

技术标签:

【中文标题】MSVS/C++:不会被优化掉的最快的总是假的条件?【英文标题】:MSVS/C++: fastest always-false condition that won't be optimized away? 【发布时间】:2021-08-11 05:36:05 【问题描述】:

我有这个代码:

if (false)

    ...code... 

编译器正在优化发布版本。我意识到它已被删除,因为它永远无法到达,但我希望里面的代码出现在发布版本中(出于某种原因)。

一个简单的解决方案是使条件依赖于编译器不会计算的函数。例如:

if (cos(0.5) == 1)

    ...code...

这没有被优化掉,因为编译器不会计算 cos(x)。

但是,我希望这种始终为假的条件尽可能少地执行,因为从未执行的代码块位于性能至关重要的较大代码段中。我知道 cos(x) 是一个可以快速评估的函数,但是我可以使用更快的函数来代替它吗(永远不会被优化掉的函数)?我正在尝试在此测试中花费尽可能少的 CPU 周期。

或者更具体地说,我如何编写一个总是返回 false、编译器无法评估、消耗的 CPU 周期比 cos(x) 少的函数?天真的尝试,例如:

bool alwaysFalse()return false;

bool alwaysFalse()return 1 == 2;

bool alwaysFalse()return (1-2) == 3;

不工作,因为编译器足够聪明,可以找出它们并优化我的代码。

【问题讨论】:

构建中没有 C++ 代码,二进制文件中只有机器代码。你是说你希望二进制文件在某些​​点包含一堆无用的机器代码? ASM 仍然是代码,这就是我所指的,是的。 也许你可以用#pragma optimize 对包围alwaysFalse() 函数? 请说明为什么您希望汇编指令仍然存在于发布版本中。你总是要面对编译器在编译时连续解析更多的表达式,所以你真的要问自己为什么不希望这种情况发生。 @VladFeinstein 因为我怀疑 OP 试图依赖于不消除死代码的特定副作用,可能是为了防止内存访问重新排序。所请求的解决方案对于该工作来说是错误的工具,因为它正式不是。 【参考方案1】:

只需将条件变量声明为 volatile 即可?

volatile bool condition = false;
if (condition)


【讨论】:

真的吗? with volatile: godbolt.org/z/f5xP3snaT without: godbolt.org/z/f5xP3snaT 如果条件“可以为真”,则内部代码块根据定义不能被优化掉。 @robthebloke 易失性自动化是一个有争议的问题。控制执行环境的编译器供应商争辩说,不可能改变自动程序的内存,因为没有其他人知道它在哪里。所以他们仍然可以假设它将评估为最后一个已知值。如果它是具有外部链接的变量,OP 可能不会看到相同 @robthebloke OP 询问 MSVC 并且您提供了 clang asm 输出。在 MSVC 中看不到 printfvolatile: godbolt.org/z/nnnTbz3E1 @phuclv 只需将volatile bool condition = false; 移出主目录 @phuclv 我标记了你,因为你的声明“在带有 volatile 的 MSVC 中看不到 printf”。如果您将该声明移出main(),您会在您的godbolt 页面上看到printf【参考方案2】:

您可以设置一个环境变量并基于该变量进行测试。

编译器在编译时无法知道环境变量的状态,所以你的代码不会被编译器优化。

我不是 C++ 程序员,但伪代码应该是这样的

boolean myVar = ENV.myVar; // Where ENV.myVar is the value of an ENV
                           // variable of name myVar evaluated to false
...

if (myVar) 
   ... code ...

否则,您可以创建一个变量并为该变量创建一个从未在您的代码上调用过的 setter,以便测试该变量的 null 值。编译器不应该优化这部分,因为它不能确定没有其他人会在运行时设置这个变量。

【讨论】:

以上是关于MSVS/C++:不会被优化掉的最快的总是假的条件?的主要内容,如果未能解决你的问题,请参考以下文章

oracle查询优化

PHP如何加速到最快

占位符可见总是假的

NSManagedObjectContext 看不到变化(“hasChanges”总是假的)

Laravel angularjs Request::ajax() 总是假的

req.isAuthenticated() 总是假的