gcc向量扩展中的未对齐加载/存储

Art*_*yom 3 c++ gcc simd clang

我需要使用GCC向量扩展来访问未对齐的值

下面的程序崩溃了 - 包括clang和gcc

typedef int __attribute__((vector_size(16))) int4;
typedef int __attribute__((vector_size(16),aligned(4))) *int4p;

int main()
{
        int v[64] __attribute__((aligned(16))) = {};
        int4p ptr = reinterpret_cast<int4p>(&v[7]);
        int4 val = *ptr;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我改变

typedef int __attribute__((vector_size(16),aligned(4))) *int4p;
Run Code Online (Sandbox Code Playgroud)

typedef int __attribute__((vector_size(16),aligned(4))) int4u;
typedef int4u *int4up;
Run Code Online (Sandbox Code Playgroud)

生成的汇编代码是正确的(使用未对齐的加载) - 在clang和gcc中.

单一定义有什么问题或者我错过了什么?clang和gcc都可以是同一个bug吗?

注意:它发生在clang和gcc中

Iwi*_*ist 6

TL; DR

您已经改变了指针类型本身的对齐方式,而不是指针类型.这与vector_size属性以及与属性有关的所有内容无关aligned.它也不是一个bug,它在GCC和Clang中都能正确实现.

很长的故事

从GCC文档中,§6.33.1公共类型属性 (重点添加):

aligned(对齐)

此属性指定指定类型的变量最小对齐(以字节为单位).[...]

有问题的类型是声明的类型,而不是 被声明的类型指向的类型.因此,

typedef int __attribute__((vector_size(16),aligned(4))) *int4p;
Run Code Online (Sandbox Code Playgroud)

声明一个新类型T,指向*T类型的对象,其中:

  • *T是一个16字节的向量,其大小默认对齐(16字节)
  • T是一种指针类型,这种类型的变量可以异常存储,与低至4字节的边界对齐(即使它们指向的是一个更加对齐的类型*T).

同时,§6.49通过内置函数使用向量指令(强调添加):

在某些目标上,指令集包含SIMD向量指令,这些指令同时对一个大寄存器中包含的多个值进行操作.例如,在x86上MMX,3DNow!和SSE扩展可以这种方式使用.

使用这些扩展的第一步是提供必要的数据类型.这应该使用适当的typedef:

typedef int v4si __attribute__ ((vector_size (16)));
Run Code Online (Sandbox Code Playgroud)

int类型指定的基本类型,而属性指定为变量的矢量的大小,以字节为单位.例如,上面的声明使编译器将v4si类型的模式设置为16字节宽,并分为int大小的单位.对于32位int,这意味着4个4字节单位的向量,foo的对应模式是V4SI.

vector_size属性仅适用于整数和浮点标量,但允许数组,指针和函数返回值与此结构一起使用.目前只允许功率为2的大小.

演示

#include <stdio.h>

typedef int __attribute__((aligned(128))) * batcrazyptr;
struct batcrazystruct{
    batcrazyptr ptr;
};

int main()
{
    printf("Ptr:    %zu\n", sizeof(batcrazyptr));
    printf("Struct: %zu\n", sizeof(batcrazystruct));
}
Run Code Online (Sandbox Code Playgroud)

输出:

Ptr:    8
Struct: 128
Run Code Online (Sandbox Code Playgroud)

这与其batcrazyptr ptr 自身的一致性有所改变,而不是它的指针,并与文档一致.

我怕你会被迫使用链typedef的,因为你有做int4u.有一个单独的属性来指定a中每个指针级别的对齐是不合理的typedef.