这段代码是编译器优化可以做什么的一个很好的例子。假设您的意思是for (a = -3; a <= 3; a++) ...
您可以将其重新编码为:
#include <stdio.h>
#define val(a) (a*a*a*a*a*a*a - a*a*a*a*4 - a*a*a + a*a*7 + 30*a)
#define MIN(X, Y) ((X) > (Y) ? (Y) : (X))
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
int main(int argc, char **argv)
{
int c = 0, d = 0, a;
for (a = -3; a <= 3; a++)
c = MAX(val(a), c), d = MIN(val(a), d);
printf("max value is %d,\nmin value is %d\n", c, d);
return 0;
}
英特尔的 ICC 直接将其变成:
4006f9:[ ...毫无意义的“ICC胶水”指令...]
4006fd: bf 7c 0b 40 00 移动 $0x400b7c,%edi
400702: 是 c5 07 00 00 移动 $0x7c5 ,%esi
400707:[ ...毫无意义的“ICC胶水”指令...]
40070e: ba 31 f6 ff ff mov $0xfffff631 ,%edx
400713: 33 c0 xor %eax,%eax
400715:[ ...毫无意义的“ICC胶水”指令...]
400719:e8 2a fe ff ff callq 400548 <printf@plt>
40071e: 33 c0 xor %eax,%eax
400720: 48 89 ec 移动 %rbp,%rsp
400723:5d 弹出 %rbp
400724:c3 retq
CLang (3.3) 也可以,它创建:
0000000000400b60 <主>:
400b60: 50 推%rax
400b61: bf 6c 0c 40 00 移动 $0x400c6c,%edi
400b66: 是 c5 07 00 00 移动 $0x7c5 ,%esi
400b6b: ba 31 f6 ff ff mov $0xfffff631 ,%edx
400b70: 30 c0 xor %al,%al
400b72: e8 39 fd ff ff callq 4008b0 <printf@plt>
400b77: 31 c0 xor %eax,%eax
400b79: 5a 弹出 %rdx
400b7a:c3 retq
在这种情况下,GCC(直到并包括 4.8.1)似乎无法进行编译时计算,当它展开循环时,它会插入一系列乘法、条件移动/SSE 最小/最大指令。
但是,如果您在代码中手动显式展开循环,那么您会得到:
c = MAX(val(-3), 0); d = MIN(val(-3), 0);
c = MAX(val(-2), c); d = MIN(val(-2), d);
c = MAX(val(-1), c); d = MIN(val(-1), d);
c = MAX(val(0), c); d = MIN(val(0), d);
c = MAX(val(1), c); d = MIN(val(1), d);
c = MAX(val(2), c); d = MIN(val(2), d);
c = MAX(val(3), c); d = MIN(val(3), d);
并且 GCC 能够在编译时计算它:
0000000000400630 <主>:
400630: 48 83 ec 08 sub $0x8,%rsp
400634: ba 31 f6 ff ff 移动 $0xfffff631 ,%edx
400639: 是 c5 07 00 00 移动 $0x7c5 ,%esi
40063e: bf 50 07 40 00 移动 $0x400750,%edi
400643: 31 c0 xor %eax,%eax
400645:e8 79 fe ff ff callq 4004c0 <printf@plt>
40064a: 31 c0 xor %eax,%eax
40064c: 48 83 c4 08 添加 $0x8,%rsp
400650:c3 retq
士气:在这种情况下,最好的结果是不尝试优化汇编器输出:)