在优化的编译器生成的程序集中看不到对函数或常量值的调用

Can't see calls to function or constant value in optimized compiler-generated assembly

我正在查看由我的普通 C++ 程序生成的程序集。完整清单是:

test_func_0(int):
        add     edi, 15
        pxor    xmm0, xmm0
        cvtsi2ss        xmm0, edi
        divss   xmm0, DWORD PTR .LC0[rip]
        cvttss2si       eax, xmm0
        ret
test_func_1(int&):
        mov     eax, DWORD PTR [rdi]
        pxor    xmm0, xmm0
        add     eax, 15
        cvtsi2ss        xmm0, eax
        divss   xmm0, DWORD PTR .LC0[rip]
        cvttss2si       eax, xmm0
        ret
test_func_2(int*):
        mov     eax, DWORD PTR [rdi]
        pxor    xmm0, xmm0
        add     eax, 15
        cvtsi2ss        xmm0, eax
        divss   xmm0, DWORD PTR .LC0[rip]
        cvttss2si       eax, xmm0
        ret
.LC1:
        .string " "
main:
        push    r12
        mov     esi, 10
        mov     edi, OFFSET FLAT:_ZSt4cout
        push    rbp
        sub     rsp, 8
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC1
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     esi, 10
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     edx, 1
        mov     esi, OFFSET FLAT:.LC1
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        mov     esi, 10
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     rbp, rax
        mov     rax, QWORD PTR [rax]
        mov     rax, QWORD PTR [rax-24]
        mov     r12, QWORD PTR [rbp+240+rax]
        test    r12, r12
        je      .L10
        cmp     BYTE PTR [r12+56], 0
        je      .L7
        movsx   esi, BYTE PTR [r12+67]
.L8:
        mov     rdi, rbp
        call    std::basic_ostream<char, std::char_traits<char> >::put(char)
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >::flush()
        add     rsp, 8
        xor     eax, eax
        pop     rbp
        pop     r12
        ret
.L7:
        mov     rdi, r12
        call    std::ctype<char>::_M_widen_init() const
        mov     rax, QWORD PTR [r12]
        mov     esi, 10
        mov     rdi, r12
        call    [QWORD PTR [rax+48]]
        movsx   esi, al
        jmp     .L8
.L10:
        call    std::__throw_bad_cast()
_GLOBAL__sub_I_test_func_0(int):
        sub     rsp, 8
        mov     edi, OFFSET FLAT:_ZStL8__ioinit
        call    std::ios_base::Init::Init() [complete object constructor]
        mov     edx, OFFSET FLAT:__dso_handle
        mov     esi, OFFSET FLAT:_ZStL8__ioinit
        mov     edi, OFFSET FLAT:_ZNSt8ios_base4InitD1Ev
        add     rsp, 8
        jmp     __cxa_atexit
.LC0:
        .long   1077936128

它是从

生成的
#include <iostream>

int test_func_0 (int my_int)
{
     return (my_int + 15) / 3.0f;
}

int test_func_1 (int& my_int)
{
     return (my_int + 15) / 3.0f;
}

int test_func_2 (int* my_int)
{
     return (*my_int + 15) / 3.0f;
}


int main()
{
    int a = 17;
  
    std::cout << test_func_0(a) << " ";
    std::cout << test_func_1(a) << " ";
    std::cout << test_func_2(&a) << std::endl;

    return 0;
}

我相信我已经能够理解其中的很多内容,但是我没有看到的三件事是:

  1. 我的函数在哪里被调用?我看到对 std::cout 的长调用(以及一个看起来很奇怪的东西 OFFSET FLAT:_ZSt4cout),但没有对 test_func_1(int&).
  2. 的显式调用
  3. 我的17去哪儿了??我可以理解它被视为 const 并在某处内联..但是在哪里?
  4. 我认为我的 17 可能是底部的 .long 1077936128,但格式很奇怪,但我不相信这一点。那么这个 1077936128 是多少?

C++ Insights 向我展示了一些帮助:

int main()
{
  int a = 17;
  std::operator<<(std::cout.operator<<(test_func_0(a)), " ");
  std::operator<<(std::cout.operator<<(test_func_1(a)), " ");
  std::cout.operator<<(test_func_2(&a)).operator<<(std::endl);
  return 0;
}

按照我的想法进行各种内联。但是我仍然没有在调用函数的程序集中看到。

  1. 您的函数都是内联的,因此 main 中没有对它们的任何调用。相反,他们的结果被直接使用。
  2. 值 17 没有出现在您的代码中,因为编译器在编译时执行了计算。所有函数return int((17+15)/3.0f) 也就是10。而且在生成的程序集中可以看到3次mov esi, 10,就是用来传值给basic:ostream::operator<<.
  3. 当从内存中读取整数时,
  4. 1077936128 是 3.0f 的表示。 (有关详细信息,请参阅 )。它仅用于这三个函数,而不用于 main(其中常量传播在编译时产生一个简单的整数)。