是的,根据 as-if 规则,编译器只有义务模拟代码的可观察行为,所以如果您有一个没有任何可观察行为的循环,则可以对其进行优化完全离开,因此实际上将有零执行时间。
示例
例如下面的代码:
int main()
{
int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
++j ;
}
}
使用-O3 标志使用gcc 4.9 编译基本上最终会缩减为以下(see it live):
main:
xorl %eax, %eax #
ret
几乎所有允许的优化都属于as-if 规则,我知道的唯一例外是copy elison,它允许影响可观察的行为。
其他一些示例包括dead code elimination,它可以删除编译器可以证明永远不会执行的代码。例如,即使以下循环确实包含副作用,也可以对其进行优化,因为我们可以证明它永远不会被执行 (see it live):
#include <stdio.h>
int main()
{
int j = 0 ;
if( false ) // The loop will never execute
{
for( int i = 0; i < 10000; ++i )
{
printf( "%d\n", j ) ;
++j ;
}
}
}
循环将与前面的示例一样优化。一个更有趣的例子是循环中的计算可以推导出为一个常数,从而避免循环的需要(不确定这属于哪个优化类别),例如:
int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
++j ;
}
printf( "%d\n", j ) ;
可以优化为 (see it live):
movl $10000, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
我们可以看到没有涉及循环。
标准中涵盖的as-if规则在哪里
as-if 规则在草案 C99 标准部分 5.1.2.3Program execution 中包含:
在抽象机中,所有表达式都按照
语义。一个实际的实现不需要评估一个
表达式,如果它可以推断出它的值没有被使用并且没有
产生了所需的副作用(包括任何由调用
函数或访问 volatile 对象)。
as-if rule 也适用于 C++,gcc 在 C++ 模式下也会产生相同的结果。 C++ 标准草案在1.9 部分中对此进行了介绍程序执行:
本国际标准中的语义描述定义了一个
参数化的非确定性抽象机。这个国际
标准对符合的结构没有要求
实施。特别是,他们不需要复制或模仿
抽象机器的结构。相反,符合要求的实现
需要模拟(仅)抽象的可观察行为
机器如下所述。5