【发布时间】:2013-06-17 16:01:03
【问题描述】:
假设我已经在全局范围内声明:
const int a =0x93191;
在主函数中我有以下条件:
if(a>0)
do_something
我注意到一个尴尬的事情是RVDS 编译器将删除if 语句并且目标文件中没有分支/jmp。
但是如果我写:
if(*(&a)>0)
do_something
if(cmp 和 branch)将在编译的目标文件中。
相比之下,GCC 使用 (-O1 或 -O2 或 -O3) 进行优化:
#include <stdio.h>
const a = 3333;
int main()
{
if (a >333)
printf("first\n");
return 0;
}
使用 -O3 编译:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000f10 <main+0>: push %rbp
0x0000000100000f11 <main+1>: mov %rsp,%rbp
0x0000000100000f14 <main+4>: lea 0x3d(%rip),%rdi # 0x100000f58
0x0000000100000f1b <main+11>: callq 0x100000f2a <dyld_stub_puts>
0x0000000100000f20 <main+16>: xor %eax,%eax
0x0000000100000f22 <main+18>: pop %rbp
0x0000000100000f23 <main+19>: retq
End of assembler dump.
对于
#include <stdio.h>
const a = 3333;
int main()
{
if (*(&a) >333)
printf("first\n");
return 0;
}
将给予:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000f10 <main+0>: push %rbp
0x0000000100000f11 <main+1>: mov %rsp,%rbp
0x0000000100000f14 <main+4>: lea 0x3d(%rip),%rdi # 0x100000f58
0x0000000100000f1b <main+11>: callq 0x100000f2a <dyld_stub_puts>
0x0000000100000f20 <main+16>: xor %eax,%eax
0x0000000100000f22 <main+18>: pop %rbp
0x0000000100000f23 <main+19>: retq
End of assembler dump.
GCC 将两者视为相同(应该如此),而 RVDS 则不同?
我尝试检查使用 volatile 的影响,在 RVDS 中它确实删除了 if(a>333),但 gcc 没有:
#include <stdio.h>
volatile const a = 3333;
int main()
{
if (a >333)
printf("first\n");
return 0;
}
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000f10 <main+0>: push %rbp
0x0000000100000f11 <main+1>: mov %rsp,%rbp
0x0000000100000f14 <main+4>: cmpl $0x14e,0x12a(%rip) # 0x100001048 <a>
0x0000000100000f1e <main+14>: jl 0x100000f2c <main+28>
0x0000000100000f20 <main+16>: lea 0x39(%rip),%rdi # 0x100000f60
0x0000000100000f27 <main+23>: callq 0x100000f36 <dyld_stub_puts>
0x0000000100000f2c <main+28>: xor %eax,%eax
0x0000000100000f2e <main+30>: pop %rbp
0x0000000100000f2f <main+31>: retq
End of assembler dump.
我使用的 RVDS 编译器版本可能存在一些错误。
【问题讨论】:
-
什么编译器和什么编译器选项?
-
@0x90
armvct我以前没听说过那个编译器?您可以发布链接以便我们更好地模拟它们吗? -
GCC 4.5.3 优化了
-O1和更高版本的分支。 -
为什么不发布 ARM 程序集转储? RVDS 的输出在哪里?除了 RVDS 这个词之外,这似乎与 ARM 无关。
-
另一个模块可以取
const的地址并改变它。在 C++ 中,没有全局const,但在 C 中有。即,编译器不必为变量分配空间。例如,const硬件寄存器可能意味着它对软件是只读的;extern const的行为更有意义。有些人可能会通过阅读标准得出结论,编译器应该同样对待这些。由于编译器需要针对所有这些情况进行优化,(*(&a))的信息可能无法通过优化器阶段,尤其是当您提供变量全局范围时。
标签: c optimization compiler-construction rvds