2016-09-19 1 views
0

Comment l'analyse d'alias fonctionne-t-elle avec des mots-clés tels que __restrict et __noalias? Est-ce que cela les considère comme une preuve de non-repliement? Ou calcule simplement ses propres résultats en fonction des pointeurs?analyse d'alias et mot-clé _restrict - C

En regardant les résultats de l'analyse d'alias de LLVM, dans de nombreuses boucles serrées qui font des séquences charges-binop magasins, le goulot d'étranglement suivant a été vu: Même si les pointeurs d'entrée et de sortie ont été largement marqués par __restrict, l'analyse d'alias encore les prenait comme 'MayAlias' et rendait les magasins à la fin de la boucle dépendant de TOUTES les charges dans la boucle.

par exemple.

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 
} 

analyse Alias ​​répond que les seules NO ALIAS sont entre:

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

Pourquoi est-il pas 'avantage' de l'utilisation du mot-clé __restrict? Est-il possible de le faire fonctionner?

est par-dessus compilé clang avec:

-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

Quels autres "no alias" attendez-vous? La liste que vous avez fournie semble couvrir toutes les entrées? – Joky

+0

Je devrais aussi attendre le% 1 -% 3,% 3 -% 5 aka le src1 - src2 etc (Vérifier le code source mis à jour) – eternalStudent

Répondre

1

Vous devez lire les règles de la norme C.

Les pointeurs "restrict" peuvent bien sûr être des alias. C'est juste que cela génère dans certains cas un comportement indéfini, donc un alias, mais le compilateur est complètement autorisé à l'ignorer. Vous devez également savoir que "restrict" n'affecte que les pointeurs dérivés d'un pointeur "restrict" par rapport aux pointeurs qui ne sont pas garantis par le même pointeur "restrict". Par exemple, si p est un pointeur "restrict" et que vous appelez f (p), cet appel pourrait stocker p dans n'importe quelle variable pointeur statique ou globale. Donc, si vous lisez une telle variable pointeur après l'appel, le compilateur ne sait pas s'il est dérivé du pointeur restrict ou non, et s'il est dérivé de p alors les règles d'alias s'appliquent.

+0

Mais selon le standard C: Il ne spécifie pas directement quand aliasing est et n'est pas possible. Cependant, il indique qu'un objet d'un type doit avoir sa valeur stockée accessible seulement par une référence qui a un d'une poignée de types apparentés. Ainsi, des paires d'accès avec des types incompatibles avec cette liste ne peuvent pas être alias. En reformulant ces règles en termes d'alias, les types qui sont compatibles lorsque les qualificateurs (const, volatile et restrict) sont sont ignorés! Voilà pourquoi ma requête ici reste ... – eternalStudent