2016-09-19 2 views
0

Wie funktioniert Alias-Analyse mit Keywords wie __restrict und __noalias? Betrachtet es sie als Beweis für kein Aliasing? Oder einfach berechnet die eigenen Ergebnisse in Abhängigkeit von den Zeigern?Alias-Analyse und _restrict Schlüsselwort - C

bei den Ergebnissen der Alias-Analyse von LLVM Sehen, in vielen engen Schleifen Lasten-binop-Store-Sequenzen zu tun, wurde die folgende Engpass gesehen: Auch wenn die Eingangs- und Ausgangszeiger mit __restrict reichlich markiert wurden, nach wie vor die Alias-Analyse nahm sie als 'MayAlias' an und machte die Speicher am Ende der Schleife abhängig von ALLEN Lasten in der Schleife.

z.B.

void _BitwiseOr_(unsigned char * __restrict * __restrict src1Addr, unsigned char * __restrict * __restrict src2Addr, unsigned char * __restrict * __restrict destAddr, unsigned int width) { 
     uchar16 * __restrict src1 = (uchar16 * __restrict) *src1Addr; 
     uchar16 * __restrict src2 = (uchar16 * __restrict) *src2Addr; 
     uchar16 * __restrict dest = (uchar16 * __restrict) *destAddr; 


     for (unsigned int i = 0; i < width; i += 4) { 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     *dest++ = *src1++ | *src2++; 
     } 
    } 

.

define void @_BitwiseOr_(i8** noalias nocapture readonly %src1Addr, i8** noalias nocapture readonly %src2Addr, i8** noalias nocapture readonly %destAddr, i32 %width) local_unnamed_addr #0 { 
entry: 
    %0 = bitcast i8** %src1Addr to <16 x i8>** 
    %1 = load <16 x i8>*, <16 x i8>** %0, align 4, !tbaa !2 
    %2 = bitcast i8** %src2Addr to <16 x i8>** 
    %3 = load <16 x i8>*, <16 x i8>** %2, align 4, !tbaa !2  
    %4 = bitcast i8** %destAddr to <16 x i8>** 
    %5 = load <16 x i8>*, <16 x i8>** %4, align 4, !tbaa !2   
    %6 = load <16 x i8>, <16 x i8>* %1, align 8, !tbaa !6 
    %7 = load <16 x i8>, <16 x i8>* %3, align 8, !tbaa !6 
    %or = or <16 x i8> %7, %6 
    store <16 x i8> %or, <16 x i8>* %5, align 8, !tbaa !6 
    ret void 
} 

Alias ​​Analyse beantwortet, dass die einzigen NO ALIASES sind zwischen:

i8** src1addr - i8** src2addr, 
i8** src1addr - i8** destaddr, 
i8** src2addr - i8** destaddr, 
i8** destaddr - i8** destaddr, 
i8** src1addr - i8** src1addr, 
i8** src2addr - i8** src2addr 

Warum tut es nicht 'Vorteil' der Verwendung von __restrict Schlüsselwort? Ist es möglich, dass es funktioniert?

Above wird von klirren mit kompiliert:

-cc1 -S -disable-free -main-file-name file.cpp -mllvm -disable-block-placement -funroll-loops -mllvm -unroll-allow-partial -mllvm -tail-merge-size=71 -mllvm -tail-dup-size=70 -fmath-errno -v -gcodeview -dwarf-column-info -coverage-file file.s -O3 -Wall -Werror=implicit-function-declaration -std=c++14 -fdeprecated-macro -fno-dwarf-directory-asm -ferror-limit 19 -fmessage-length 0 -ffreestanding -fallow-half-arguments-and-returns -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -mllvm -no-phi-elim-live-out-early-exit -mllvm -use-cfl-aa=anders -mllvm -use-cfl-aa-in-codegen=anders -mllvm -debug -mllvm -da-delinearize -mllvm -mllvm -enable-tbaa -mllvm -enable-scoped-noalias -mllvm -evaluate-aa-metadata -mllvm -print-all-alias-modref-info 
+0

Welche anderen "no-Aliase" erwarten Sie? Die von Ihnen bereitgestellte Liste scheint alle Eingaben abzudecken. – Joky

+0

Ich sollte auch die% 1 -% 3,% 3 -% 5 alias die src1 - src2 usw. erwarten (aktualisierten Quellcode prüfen) – eternalStudent

Antwort

1

Sie die Regeln im C-Standard lesen müssen.

"beschränken" Zeiger können natürlich Alias. Es ist nur, dass dies in einigen Fällen undefiniertes Verhalten generiert, so dass sie Alias, aber der Compiler ist völlig erlaubt, dies zu ignorieren.

Sie müssen auch beachten, dass "beschränken" nur Zeiger betrifft, die von einem "beschränken" Zeiger gegenüber Zeigern abgeleitet sind, die garantiert nicht vom gleichen "beschränken" -Zeiger abgeleitet sind. Wenn zum Beispiel p ein "restrict" -Zeiger ist und Sie f (p) aufrufen, könnte dieser Aufruf p in eine beliebige statische oder globale Zeigervariable speichern. Wenn Sie also nach dem Aufruf eine solche Zeigervariable lesen, weiß der Compiler nicht, ob er vom Begrenzungszeiger abgeleitet ist oder nicht, und wenn er von p abgeleitet wird, gelten Aliasregeln.

+0

Aber nach dem C-Standard: Es wird nicht direkt angegeben, wenn Aliasing ist und nicht möglich ist. Es gibt jedoch , dass ein Objekt eines Typs seinen gespeicherten Wert nur durch eine Referenz zugegriffen werden soll, die eine einer Handvoll verwandter Typen hat. Implizit, dann Paare von Zugriffen mit Typen nicht konsistent diese Liste kann nicht Alias. Wenn diese Regeln in Bezug auf das Aliasing wieder hergestellt werden, werden die Typen, die mit den Qualifikationsmerkmalen (const, volatile und restricte) kompatibel sind, ignoriert! Deshalb bleibt meine Frage hier ... – eternalStudent