GCC -O3为std :: uninitialized_default_construct生成奇怪的程序集

时间:2019-09-13 11:06:57

标签: c++ gcc assembly optimization x86-64

我正在查看GCC 9.1为新(C ++ 17)函数std :: uninitialized_default_construct生成的程序集。在大多数情况下(MSVC,Clang甚至是较旧的GCC),这就是您所期望的:调用(或内联)类型T的默认构造函数的循环。

由于某些原因,GCC从7到当前以-03运行会生成我不完全了解的程序集。尤其是一开始看起来像哈希的部分。

我正在使用“ -O3 -std = c ++ 17 -fno-stack-protector -fno-exceptions -fomit-frame-pointer -fno-unroll-loops”进行编译。我在这里想念东西吗?

在各种编译器上测试了相同的代码。没有人表现得很奇怪。我没有找到关于哈希的解释。

测试代码(通过godbolt.org运行):

#include <iostream>
#include <algorithm>
#include <memory>
#include <string>
#include <stdio.h>

struct Vector3 {
    float x=0,y=0,z=0; 
};

template< typename T >
static int init(T* mem, size_t len)
{
    std::uninitialized_default_construct(mem, mem+len);     
    return 0;
}

template< typename T >
static int init2(T* mem, size_t len)
{
    auto end = mem + len;
    while (mem < end)
        new (mem++) T();
    return 0;
}

int main(int argc, char** argv)
{
    Vector3 mem[100];
    auto funcPtr = (argc > 2) ? &init<Vector3> : &init2<Vector3>;

    if (0 != funcPtr(mem, (int)atoi(argv[1])))
        return -1;
    printf("%f\n", mem[0].x);
    return 0;
}

函数“ init”的生成反汇编(做好准备):

int init<Vector3>(Vector3*, unsigned long):
        lea     rax, [rsi+rsi*2]
        lea     rcx, [rdi+rax*4]
        cmp     rcx, rdi
        je      .L2
        movabs  rsi, 3074457345618258603
        mov     rdx, rcx
        mov     rax, rdi
        sub     rdx, rdi
        sub     rdx, 12
        shr     rdx, 2
        imul    rdx, rsi
        movabs  rsi, 4611686018427387903
        and     rdx, rsi
        lea     rsi, [rdx+1]
        cmp     rdx, 2
        jbe     .L3
        mov     rdx, rsi
        pxor    xmm0, xmm0
        shr     rdx, 2
        lea     rdx, [rdx+rdx*2]
        sal     rdx, 4
        add     rdx, rdi
.L4:
        movups  XMMWORD PTR [rax], xmm0
        add     rax, 48
        movups  XMMWORD PTR [rax-32], xmm0
        movups  XMMWORD PTR [rax-16], xmm0
        cmp     rax, rdx
        jne     .L4
        mov     rax, rsi
        and     rax, -4
        lea     rdx, [rax+rax*2]
        lea     rdi, [rdi+rdx*4]
        cmp     rsi, rax
        je      .L2
.L3:
        lea     rax, [rdi+12]
        mov     QWORD PTR [rdi], 0
        mov     DWORD PTR [rdi+8], 0x00000000
        cmp     rcx, rax
        je      .L2
        lea     rax, [rdi+24]
        mov     QWORD PTR [rdi+12], 0
        mov     DWORD PTR [rdi+20], 0x00000000
        cmp     rcx, rax
        je      .L2
        mov     QWORD PTR [rdi+24], 0
        mov     DWORD PTR [rdi+32], 0x00000000
.L2:
        xor     eax, eax
        ret

为进行比较,这是MSVC为相同代码生成的:

int init<Vector3>(Vector3 *,unsigned __int64) PROC         ; init<Vector3>, COMDAT
        lea     rax, QWORD PTR [rdx+rdx*2]
        lea     rdx, QWORD PTR [rcx+rax*4]
        xor     eax, eax
        cmp     rcx, rdx
        je      SHORT $LN5@init
        npad    1
$LL6@init:
        mov     QWORD PTR [rcx], rax
        mov     DWORD PTR [rcx+8], eax
        add     rcx, 12
        cmp     rcx, rdx
        jne     SHORT $LL6@init
$LN5@init:
        ret     0

有没有办法使GCC正常运行?

0 个答案:

没有答案