是否有可能执行时间为零的循环?我认为即使是一个空循环也应该有一个执行时间,因为存在与之相关的开销。
是否有可能执行时间为零的循环?我认为即使是一个空循环也应该有一个执行时间,因为存在与之相关的开销。
Answers:
是的,在假设规则下,编译器仅需模拟代码的可观察行为,因此,如果您的循环没有任何可观察的行为,则可以对其进行完全优化,因此有效执行时间为零。
例子
例如下面的代码:
int main()
{
int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
++j ;
}
}
gcc 4.9
使用-O3
flag编译的结果基本上减少到以下内容(请参见live):
main:
xorl %eax, %eax #
ret
几乎所有允许的优化都属于“假设”规则,我知道的唯一例外是复制Elison,它可以实现可观察的行为。
其他一些示例包括消除无效代码,这些代码可以删除编译器可以证明永远不会执行的代码。例如,即使以下循环确实包含副作用,也可以对其进行优化,因为我们可以证明它永远不会被执行(实时查看):
#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 ) ;
可以优化为(观看直播):
movl $10000, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
我们可以看到不涉及循环。
该标准涵盖的规则在哪里
在AS-如果规则被覆盖在C99标准草案,5.1.2.3
计划执行它说:
在抽象机中,所有表达式均按语义指定的方式求值。如果实际实现可以推断出未使用其值并且没有产生所需的副作用(包括由调用函数或访问易失性对象引起的副作用),则无需对表达式的一部分进行求值。
该AS-如果规则也适用于C ++,gcc
会产生在C ++中模式相同的结果为好。C ++标准草案在1.9
程序执行部分中对此进行了介绍:
本国际标准中的语义描述定义了参数化的不确定性抽象机器。本国际标准对一致性实现的结构没有要求。特别是,它们不需要复制或模拟抽象机的结构。相反,需要遵循实现以(仅)模拟抽象机的可观察行为,如下所述。5
除了优化编译器外,某些CPU架构(尤其是DSP)的开销循环为零,因此硬件可以有效地优化具有固定迭代次数的循环,请参见例如http://www.dsprelated.com/showmessage/20681 /1.php
编译器没有义务评估没有副作用且其结果被丢弃的表达式或表达式的一部分。
Harbison和Steele,C:参考手册