如何从非限制指针创建限制指针

问题描述 投票:0回答:1

这是一个激励人心的例子

void foo(int *A, int *B, int *N) {
  for (int k = 0; k < *N; k++)
    A[k] += B[k];
}

编译器无法向量化此循环,因为它假定 A 和 N 别名。将

restrict
添加到 N 可以实现矢量化。例如,https://godbolt.org/z/joMrhEM8K

void foo(int *A, int *B, int *__restrict N) {
    for (int k = 0; k < *N; k++)
        A[k] += B[k];
}

生成

.LBB0_9:
        ldp     q0, q3, [x11, #-16]
        subs    x12, x12, #8
        ldp     q1, q2, [x10, #-16]
        add     x10, x10, #32
        add     v0.4s, v0.4s, v1.4s
        add     v1.4s, v3.4s, v2.4s
        stp     q0, q1, [x11, #-16]
        add     x11, x11, #32
        b.ne    .LBB0_9

这很好。但我想从 N 中创建一个

restrict
ed 指针,而不修改函数声明。例如,类似

void foo(int *A, int *B, int *N) {
    int *__restrict p = N;
    for (int k = 0; k < *p; k++)
        A[k] += B[k];
}

但这行不通。有什么办法可以实现这个目标吗?

我想实现这一点的原因是因为这样我就可以对代码进行“版本化”,而无需在声明中添加 __restrict 。喜欢:

// Returns true if X, Y don't alias.
bool no_alias(int* X, int *Y);

void foo(int *A, int *B, int *N) {
    if (no_alias(A,N)) { // assuming I have a way to figure out that A and N don't alias at runtime.
      int *__restrict p = N;
      for (int k = 0; k < *p; k++)
        A[k] += B[k];
    } else {
      for (int k = 0; k < *p; k++)
          A[k] += B[k];
    }
}
c++ c loops optimization compiler-optimization
1个回答
0
投票

您必须使用内置函数

__builtin_assume

#include <cassert>

bool no_alias(int* X, int* Y);

void foo(int *A, int *B, int *N) {
    int* p = N;
    if (no_alias(A, N)) {
        __builtin_assume(p != A);
    }
    for (int k = 0; k < *p; k++) {
        A[k] += B[k];
    }
}

也许添加编译选项

-fstrict-aliasing
gcc、严格别名和恐怖故事

© www.soinside.com 2019 - 2024. All rights reserved.