c++ - gcc vector 扩展中的未对齐加载/存储

标签 c++ gcc clang simd

我需要使用 GCC vector 扩展访问未对齐的值

下面的程序在 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;
}

但是如果我改变

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

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

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

单一定义有什么问题或我遗漏了什么? clang 和 gcc 会不会是同一个 bug?

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

最佳答案

长话短说

您更改了指针类型本身的对齐方式,而不是pointee类型。这与 vector_size 属性无关,而与 aligned 属性有关。它也不是错误,并且在 GCC 和 Clang 中都正确实现了。

说来话长

来自 GCC 文档,§ 6.33.1 Common Type Attributes (强调):

aligned (alignment)

This attribute specifies a minimum alignment (in bytes) for variables of the specified type. [...]

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

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

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

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

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

On some targets, the instruction set contains SIMD vector instructions which operate on multiple values contained in one large register at the same time. For example, on the x86 the MMX, 3DNow! and SSE extensions can be used this way.

The first step in using these extensions is to provide the necessary data types. This should be done using an appropriate typedef:

typedef int v4si __attribute__ ((vector_size (16)));

The int type specifies the base type, while the attribute specifies the vector size for the variable, measured in bytes. For example, the declaration above causes the compiler to set the mode for the v4si type to be 16 bytes wide and divided into int sized units. For a 32-bit int this means a vector of 4 units of 4 bytes, and the corresponding mode of foo is V4SI.

The vector_size attribute is only applicable to integral and float scalars, although arrays, pointers, and function return values are allowed in conjunction with this construct. Only sizes that are a power of two are currently allowed.

演示

#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 中使用单独的属性来指定每个指针级别的对齐方式是不合理的。

关于c++ - gcc vector 扩展中的未对齐加载/存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41931278/

相关文章:

c++ - 如何在 C++ 中使用 utf8 字符数组?

c++ - std::sort 是否检查 vector 是否已经排序?

c++ - noexcept(false) 析构函数覆盖所有特殊成员函数的异常规范?

Clang:在哪里定义了 -Wall 选项?

linux - 未找到体系结构 x86_64、macOS Sierra

c - 在 clang 中使用 realloc 来缩小内存

c++ - 为什么要使用非成员函数?

c++ - 如何优化这个 find_if 代码?

c++ - 在 macOS High Sierra 上使用 node-gyp 动态链接 wfdb 库时未加载符号

c - 为什么 clang 无法展开循环(gcc 展开)?