You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:47:59