如何指示结构成员没有别名?

时间:2018-09-22 22:22:23

标签: c++ gcc strict-aliasing restrict

如果您编写如下语句:

a[i] = b[i] + c[i];

......您可能想向编译器指示a[i]b[i]c[i]指向内存中的不同位置,从而实现各种优化(例如矢量化)。这可以通过在声明中添加特殊关键字来完成:

float * __restrict__ a; // same for b and c

但是,如果您使用的是更复杂的对象而不是float,该怎么办?

struct item {
    float foo, bar;
};

考虑以下代码:

float *a, *b;
item *c;
// ...
for (int i = 0; i < 42; ++i) {
    a[i] = b[i] * c[i].foo + c[i].bar;
}

在循环中,编译器并不关心c[i],而是关心c[i].fooc[i].bar。在这种情况下,如何针对结构的各个字段声明关于指针独立性的等效断言?

3 个答案:

答案 0 :(得分:1)

For now, I have managed to solve the problem using:

#pragma GCC ivdep

However, this turns off the dependency checking completely. I would still be interested in more selective solution.

答案 1 :(得分:1)

该标准不要求编译器适应使用a[anything]b[anything]来访问struct item的任何部分的可能性。它列出了实现必须始终允许使用它们来访问诸如struct item之类的结构的左值的类型,而诸如int之类的非字符成员类型不在其中。无需特殊许可即可让编译器假定ab都不会为struct item加上别名。

当然,对于编译器来说,允许代码获取非字符类型的struct或union成员的地址将是无济于事的,即使在某些情况下,也绝不允许实际使用所得的指针来访问该成员不涉及别名(*)的内容。该标准在涉及别名的情况与不涉及别名的情况之间没有区别,并且留下了何时允许使用成员类型的左值访问结构的问题完全取决于实现者的判断。 gcc和clang的作者可能已经决定,在非锯齿情况下支持在结构成员上使用指针的最简单方法是在所有情况下都支持它们,但是该标准几乎不需要这种处理,并且我认为作者希望这样做。

该标准为实现提供了受益于以下假设的空间:a而非b都不会别名c,但仍支持大多数需要使用结构指针或结构指针的程序。工会会员。在某些情况下,更多类似于__restrict的限定符会有所帮助,但我不确定在您展示的情况下,您认为实施还需要什么额外的权限。

(*),即在存在较新的指针/引用(也将用于访问或寻址)的情况下,没有任何操作访问存储区域或派生用于此操作的指针/引用的情况冲突的方式存储相同的存储空间。

答案 2 :(得分:0)

没有必要这样做。

要么编译器足够聪明,以至于知道这些结构成员不能使用别名,要么编译器不足以对这些信息做任何有用的事情。

使用__restrict__和C99 restrict关键字的原因是因为与结构不同,数组可能会别名。因此,关键字为编译器提供了真正有用的信息。