2016-09-19 116 views
0

別名分析如何與關鍵字__restrict__noalias一起使用? 它是否認爲它們是沒有鋸齒的證據? 或者根據指針簡單計算自己的結果?別名分析和_restrict關鍵字 - C

望着LLVM的別名分析,在許多緊密循環做負載-binop店序列的結果,下面的瓶頸看到:即使 輸入和輸出指針用__restrict,別名分析仍然充分標假設它們爲'MayAlias',並使循環結束時的商店依賴於循環中的所有負載。

例如

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 
} 

別名分析回答,唯一的NO別名之間:

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

爲何不使用__restrict關鍵字的「好處」? 是否有可能使其工作?

以上是通過用鏗鏘編譯:

-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

你還期待什麼其他的「別名」?你提供的列表似乎涵蓋了所有的輸入? – Joky

+0

我還應該期待%1 - %3,%3 - %5 aka src1 - src2等(檢查更新後的源代碼) – eternalStudent

回答

1

您需要閱讀在C標準的規則。

「限制」指針當然可以是別名。只是這在某些情況下會產生未定義的行爲,所以它們是別名,但編譯器完全可以忽略它。

您還需要知道,「restrict」隻影響從「restrict」指針派生的指針,而不是從相同的「restrict」指針派生的指針。例如,如果p是一個「限制」指針並且你調用f(p),那麼這個調用可以將p存儲到任何靜態或全局指針變量中。因此,如果在調用之後讀取這樣的指針變量,編譯器不知道它是否從限制指針派生,並且如果它是從p派生的,則應用別名規則。

+0

但是根據C標準:它不會直接指定何時出現混疊並且不可能。但是,它聲明 一個類型的對象應該只有一個引用有一個相關類型的訪問,才能訪問其存儲的值。那麼,顯式地,那些類型與 列表不一致的訪問對不能被別名訪問。以混疊方式重申這些規則,忽略限定符(常量,易失性和限制)時兼容的類型爲 !這就是爲什麼我的查詢仍然存在... – eternalStudent