У меня есть такая программа, в которой я абстрагирую указатели с помощью класса. Я хотел бы, чтобы компилятор оптимизировал развернутый 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
Но я бы хотел абстрагироваться от этого в классе и не требовать, чтобы пользователь писал лямбда-конструкцию для достижения результата для простоты использовать, а также чтобы не пропустить эту оптимизацию.