如何强制编译器将“ 4的向量”包装器类作为单个XMM寄存器传递?

我正在尝试优化一个小的“ 4浮点数的矢量”包装器类,当然,我也想使其变得方便。例如:

typedef float v4f __attribute__ ((vector_size (16)));

struct V4 {

    union {
        v4f packed;
#if 1
        struct { float r,g,b,a; };
#endif
#if 1
        float data[4];
#endif
    };

    V4() = default;
    V4(v4f v) : packed(v) {}
};

V4 AddV4(V4 a,V4 b) { 
    return a.packed + b.packed; 
}
V4 MulV4(V4 a,V4 b) { 
    return a.packed * b.packed; 
}

static_assert(sizeof(V4) == 16);

我知道联盟在理论上是未定义的行为,但实际上,它工作正常;-)

问题如下:我使用gcc和clang并通过命令行参数在godbolt中对此进行了测试(请参阅https://godbolt.org/z/fXbtre

-O3  -fomit-frame-pointer -fno-rtti -fno-exceptions -mavx -ffast-math 

如果我从联合中同时禁用了结构和数组(即都将其设置为#if 0),则会得到一个非常紧凑的AddV4和MulV4函数,例如:

AddV4(V4,V4):
        vaddps  xmm0,xmm0,xmm1
        ret

但是,如果我启用这两个中的任何一个,我都会得到:

AddV4(V4,V4):
        vmovq   QWORD PTR [rsp-32],xmm1
        vmovq   QWORD PTR [rsp-40],xmm0
        vmovaps xmm5,XMMWORD PTR [rsp-40]
        vmovq   QWORD PTR [rsp-24],xmm2
        vmovq   QWORD PTR [rsp-16],xmm3
        vaddps  xmm4,xmm5,XMMWORD PTR [rsp-24]
        vmovaps XMMWORD PTR [rsp-40],xmm4
        mov     rax,QWORD PTR [rsp-32]
        vmovq   xmm0,QWORD PTR [rsp-40]
        vmovq   xmm1,rax
        mov     QWORD PTR [rsp-24],rax
        ret

有人可以解释为什么吗?我可以使用gcc / clang的编译器标志来解决此问题吗?还是仅使用打包数据结构的唯一选择? (在那种情况下,我需要编写访问器方法x(),y(),z(),w(),这在我们的代码库中将是一个很大的变化,因此,我会优先选择其他方法。)

hanzilou 回答:如何强制编译器将“ 4的向量”包装器类作为单个XMM寄存器传递?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3097027.html

大家都在问