首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >__attribute__ ((vector_size))魔法被联盟摧毁

__attribute__ ((vector_size))魔法被联盟摧毁
EN

Stack Overflow用户
提问于 2022-03-17 05:23:22
回答 2查看 80关注 0票数 1

使用godbolt.org x86-64 gcc 11.2这个代码..。

代码语言:javascript
复制
typedef int v4i __attribute__ ((vector_size (16)));

typedef union {
    v4i v;
} int4;

int4 mul(int4 l, int4 r)
{
    return (int4){.v=l.v * r.v};
}

...produces此程序集(当使用-O3 -mavx编译时).

代码语言:javascript
复制
mul:
        vpmulld xmm0, xmm0, xmm1
        ret

但是这个密码..。

代码语言:javascript
复制
typedef int v4i __attribute__ ((vector_size (16)));

typedef union {
    v4i v;
    struct {int x,y,z,w;}; // this line is the change
    int i[4]; // this one too
} int4;

int4 mul(int4 l, int4 r)
{
    return (int4){.v=l.v * r.v};
}

...produces此程序集(当也使用-O3 -mavx编译时).

代码语言:javascript
复制
mul:
        mov     QWORD PTR [rsp-40], rdi
        mov     QWORD PTR [rsp-32], rsi
        vmovdqa xmm1, XMMWORD PTR [rsp-40]
        mov     QWORD PTR [rsp-24], rdx
        mov     QWORD PTR [rsp-16], rcx
        vpmulld xmm0, xmm1, XMMWORD PTR [rsp-24]
        vmovdqa XMMWORD PTR [rsp-40], xmm0
        mov     rax, QWORD PTR [rsp-40]
        mov     rdx, QWORD PTR [rsp-32]
        ret

x86-64 clang 13.0.1也有类似的结果

所以我的问题是,我如何说服gcc (和/或clang)这两个代码块应该产生相同的输出?

我尝试过__attribute__ ((aligned)),移除int i[4];struct,将__attribute__ ((packed))应用于struct,甚至给__attribute__ ((transparent_union))一次尝试。无论__attribute__ ((vector_size (16)))赋予什么神奇状态,都可以通过向union添加任何内容来打破它。

EN

回答 2

Stack Overflow用户

发布于 2022-03-17 06:01:03

我应该说,我从来没有亲自处理过这个属性,我刚才检查了gcc,但是从文件中我看到了一些我认为对你的问题有用的东西。

从您的代码中,我可以假设您希望使用union分别访问向量的每个int。但是,如果这是唯一的原因,就没有必要使用int[4]struct {int x,y,z,w;};作为联合的一部分,因为向量可以像数组一样使用:

代码语言:javascript
复制
typedef int v4i __attribute__ ((vector_size (16)));

typedef union {
    v4i v;
} int4;

int4 mul(int4 l, int4 r)
{
    int4 ret = (int4){.v=l.v * r.v};
    printf("%i %i %i %i", ret.v[0], ret.v[1], ret.v[2], ret.v[3]);
    return ret;
}

代码将根据您的喜好进行优化。此外,如果您需要字节级访问,union与另一个向量一起工作也可以:

代码语言:javascript
复制
typedef int v4i __attribute__ ((vector_size (16)));
typedef unsigned char v4b __attribute__ ((vector_size (16)));

struct i4s{int x,y,z,w;};

typedef union {
    v4i v;
    v4b v2;
} int4;

int4 mul(int4 l, int4 r)
{
    return (int4){.v=l.v * r.v};
}

在这种情况下,union似乎将使用类似于原语的类型。例如,甚至连__m128i也能工作。

票数 0
EN

Stack Overflow用户

发布于 2022-03-17 08:00:30

结果,他们是一样的。出于某种原因,第二种方法包括填充xmm?从堆栈中注册,但是如果添加一个主函数.

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    // volatile keyword added so they don't get optimised out   
    volatile int4 x = {.v={1,2,3,4}};
    volatile int4 y = {.v={1,2,3,4}};
    int4 z = mul(x, y);
    
    return z.v[0];
}

...then函数(在本例中为单个vpmulld指令)被内联,并插入不同的、适当的堆栈操作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71507434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档