如何阻止GCC将return指令替换为跳转到最后一条的jmp指令
如何阻止GCC在-O0下将return替换为统一跳转的优化?
在使用-O0禁用大多数优化的情况下,GCC会将以下C函数编译为对应的汇编代码:
int dummy_function(int x) { if (x == 1) { return 1; } else if (x == 2) { return 2; } else if (x == 3) { return 3; } else if (x == 4) { return 4; } else if (x == 5) { return 5; } else if (x == 6) { return 6; } else { return 10; } }
编译后的汇编代码如下:
0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 89 7d fc mov DWORD PTR [rbp-0x4],edi 7: 83 7d fc 01 cmp DWORD PTR [rbp-0x4],0x1 b: 75 07 jne 14 <test+0x14> d: b8 01 00 00 00 mov eax,0x1 12: eb 46 jmp 5a <test+0x5a> 14: 83 7d fc 02 cmp DWORD PTR [rbp-0x4],0x2 18: 75 07 jne 21 <test+0x21> 1a: b8 02 00 00 00 mov eax,0x2 1f: eb 39 jmp 5a <test+0x5a> 21: 83 7d fc 03 cmp DWORD PTR [rbp-0x4],0x3 25: 75 07 jne 2e <test+0x2e> 27: b8 03 00 00 00 mov eax,0x3 2c: eb 2c jmp 5a <test+0x5a> 2e: 83 7d fc 04 cmp DWORD PTR [rbp-0x4],0x4 32: 75 07 jne 3b <test+0x3b> 34: b8 04 00 00 00 mov eax,0x4 39: eb 1f jmp 5a <test+0x5a> 3b: 83 7d fc 05 cmp DWORD PTR [rbp-0x4],0x5 3f: 75 07 jne 48 <test+0x48> 41: b8 05 00 00 00 mov eax,0x5 46: eb 12 jmp 5a <test+0x5a> 48: 83 7d fc 06 cmp DWORD PTR [rbp-0x4],0x6 4c: 75 07 jne 55 <test+0x55> 4e: b8 06 00 00 00 mov eax,0x6 53: eb 05 jmp 5a <test+0x5a> 55: b8 0a 00 00 00 mov eax,0xa 5a: 5d pop rbp 5b: c3 ret
可以看到,即便启用了-O0,GCC仍会将各分支中的return替换为跳转到函数末尾统一ret的jmp指令。要阻止这个优化,有两种可行方法:
- 全局禁用该优化:编译时添加
-fno-optimize-sibling-calls选项,该选项会禁用兄弟调用相关的优化,强制GCC在每个分支生成独立的ret指令。 - 仅对目标函数禁用:给目标函数添加
__attribute__((optimize("-fno-optimize-sibling-calls")))属性,避免影响其他代码,示例代码如下:
__attribute__((optimize("-fno-optimize-sibling-calls"))) int dummy_function(int x) { if (x == 1) { return 1; } else if (x == 2) { return 2; } else if (x == 3) { return 3; } else if (x == 4) { return 4; } else if (x == 5) { return 5; } else if (x == 6) { return 6; } else { return 10; } }
内容的提问来源于stack exchange,提问作者Yacine Hebbal
相关产品推荐
相关产品推荐

