Ограничить квалификатор указателей на члены класса - PullRequest
0 голосов
/ 21 июня 2020

У меня есть такая программа, в которой я абстрагирую указатели с помощью класса. Я хотел бы, чтобы компилятор оптимизировал развернутый l oop в функции main ниже, предполагая отсутствие псевдонима указателя. Как я могу эффективно использовать конструкцию __restrict в этом сценарии? Я использую Clang с бэкэндом RIS C -V.

extern int* getPtr(int n); // Runtime function providing data

class RemotePtr {
  private:
    int* a;

  public:
    RemotePtr(int* a) : a(a) {}

    int& at(int n) {
      return a[n];
    }
};

int main(int argc, char** argv) {
  int* A = getPtr(0);
  int* B = getPtr(1);

  RemotePtr a(A);
  RemotePtr b(B);

  // This loop should be compiled assuming no aliasing between 
  // pointers `a.a` and `b.a`
  #pragma unroll 4
  for(int i=0; i<4; ++i) {
    a.at(i) += b.at(i);
  }

  return 0;
}

Ниже приведен пример использования classi c для __restrict, и когда я его компилирую, я вижу noalias, аннотированный в LLVM IR по желанию.

int* A;
int* B;

void vec_add(int* __restrict a, int* __restrict b, int n) {
  #pragma unroll 4
  for(int i=0; i<n; ++i) {
    a[i] += b[i];
  }
}

int main(int argc, char** argv) {
  vec_add(A, B, 4);
  return 0;
}

Фрагмент результирующего IR:

; Function Attrs: nofree norecurse nounwind
define dso_local void @_Z7vec_addPiS_i(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i32 %n) local_unnamed_a
ddr #0 {
entry:
  %cmp6 = icmp sgt i32 %n, 0
  br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:                               ; preds = %entry
  %0 = add nsw i32 %n, -1
  %xtraiter = and i32 %n, 3

Наконец, изменение строки a.at(i) += b.at(i); на вызов лямбда-функции с ограничением, похоже, работает:

([&](int& __restrict a, int& __restrict b) {a += b;})(a.at(i), b.at(i));

Думаю, это дает то, что я хочу:

; Function Attrs: norecurse nounwind
define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 {
entry:
  %0 = load i32*, i32** @A, align 4, !tbaa !3
  %1 = load i32*, i32** @B, align 4, !tbaa !3
  %2 = load i32, i32* %1, align 4, !tbaa !7, !alias.scope !9, !noalias !12
  %3 = load i32, i32* %0, align 4, !tbaa !7, !alias.scope !12, !noalias !9

Но я бы хотел абстрагироваться от этого в классе и не требовать, чтобы пользователь писал лямбда-конструкцию для достижения результата для простоты использовать, а также чтобы не пропустить эту оптимизацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...