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

时间:2017-01-30 08:07:17

标签: c++ gcc clang simd

我需要使用GCC向量扩展

来访问未对齐的值

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

CREATE TABLE `a` (
  `ID` int(11) NOT NULL,
  `date` datetime DEFAULT,
  PRIMARY KEY (`ID`),
  KEY `date` (`date`),
) 

CREATE TABLE `b` (
  `bID` int(11) NOT NULL,
  `ID` int(11)  NOT NULL,
  `cID` int(11) DEFAULT,
  PRIMARY KEY (`bID`),
  KEY `cID` (`cID`),
)

但是,如果我改变

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;
}

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

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

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

注意:它在clang和gcc中都会发生

1 个答案:

答案 0 :(得分:6)

TL; DR

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

长篇故事

在GCC文档中,§ 6.33.1 Common Type Attributes (重点已添加)

  

aligned路线

     

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

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

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

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

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

与此同时,§ 6.49 Using Vector Instructions through Built-in Functions(强调添加)

  

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

     

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

来完成
typedef int v4si __attribute__ ((vector_size (16)));
     

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

     

vector_size属性仅适用于整数和浮点标量,但数组,指针和函数返回值与此结构一起使用。仅限大小的幂目前允许两个。

演示

#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));
}

输出:

Ptr:    8
Struct: 128

这与batcrazyptr ptr 本身一致,其对齐要求已更改,而不是其指针,并与文档一致。

解决方案

我害怕你被迫使用typedef链,正如你对int4u所做的那样。有一个单独的属性来指定typedef中每个指针级别的对齐方式是不合理的。