GCC显示已内联std::div函数但实际汇编未生成内联代码的问题咨询
GCC显示已内联std::div函数但实际汇编未生成内联代码的问题咨询
我最近在Godbolt上随手对比MSVC和GCC的优化效果时,遇到了一个很奇怪的矛盾问题:GCC的优化日志明确显示它已经内联了所有对std::div的调用,但生成的汇编代码里却仍然保留了对ldiv的调用,完全没有内联的迹象。
先给大家看一下我的测试代码:
auto funcA(std::int_fast16_t a, std::int_fast16_t b) { auto div{std::div(a, b)}; return div.quot + !!div.rem; } auto funcB(std::int_fast16_t a, std::int_fast16_t b) { auto div{std::div(a, b)}; return div.quot + (div.rem != 0); } auto funcC(std::int_fast16_t a, std::int_fast16_t b) { auto div{std::div(a, b)}; auto repetitions{div.quot}; if (div.rem != 0) ++repetitions; return repetitions; }
从Godbolt和本地GCC 11.4.0输出的优化日志来看,每个函数都明确标注了内联std::div的过程:
优化日志核心片段:
Inlined 3 calls, eliminated 0 functions [...] auto funcA(std::int_fast16_t a, std::int_fast16_t b) { Considering inline candidate ldiv_t std::div(long int, long int)/17. Inlining ldiv_t std::div(long int, long int)/17 into auto funcA(int_fast16_t, int_fast16_t)/19. auto div{std::div(a, b)}; return div.quot + !!div.rem; } auto funcB(std::int_fast16_t a, std::int_fast16_t b) { Considering inline candidate ldiv_t std::div(long int, long int)/17. Inlining ldiv_t std::div(long int, long int)/17 into auto funcB(int_fast16_t, int_fast16_t)/20. auto div{std::div(a, b)}; return div.quot + (div.rem != 0); } auto funcC(std::int_fast16_t a, std::int_fast16_t b) { Considering inline candidate ldiv_t std::div(long int, long int)/17. Inlining ldiv_t std::div(long int, long int)/17 into auto funcC(int_fast16_t, int_fast16_t)/21. auto div{std::div(a, b)}; auto repetitions{div.quot}; if (div.rem != 0) ++repetitions; return repetitions; }另外日志里提到的
funcB内联失败提示,是指funcB到funcA的内联,和std::div的内联无关。
但实际生成的汇编代码却和日志完全不符,三个函数要么直接调用ldiv,要么跳转到其他调用ldiv的函数:
"funcA(long, long)": push rax call "ldiv" cmp rdx, 1 pop rdx sbb rax, -1 ret "funcB(long, long)": jmp "funcA(long, long)" "funcC(long, long)": push rax call "ldiv" cmp rdx, 1 pop rdx sbb rax, -1 ret
我在本地用GCC 11.4.0完整复现了这个问题:给函数加上extern "C"以方便识别汇编里的名称,执行的编译命令是:
gcc -masm=intel -fno-verbose-asm -S -fdiagnostics-color=always -fopt-info-all=all.opt -std=c++2a -Os -finline-functions test.cpp
生成的all.opt文件同样显示内联了std::div,但test.s里依然存在call ldiv的指令。
我现在完全摸不着头绪:是我误解了GCC优化日志的含义吗?还是这个“Opt Remarks”视图本身存在bug?本来以为这个工具能帮我更好地分析优化过程,但在这么简单的测试用例上就出现矛盾,实在让人困惑。有没有人能解释这背后的原因,或者告诉我怎么才能让日志和实际汇编结果保持一致?
内容来源于stack exchange
相关产品推荐
相关产品推荐

