别名分析和_restrict关键字 - C.

时间:2016-09-19 08:46:55

标签: c llvm alias static-analysis restrict

别名分析如何与__restrict__noalias等关键字一起使用? 它是否将它们视为没有混叠的证据? 或者根据指针简单地计算自己的结果?

查看LLVM的别名分析结果,在执行load-binop-store序列的许多紧密循环中,出现了以下瓶颈: 尽管输入和输出指针已经用__restrict充分标记,但别名分析仍然将它们假设为“MayAlias”,并使循环结束时的存储依赖于循环中的所有负载。

e.g。

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
}

别名分析回答说,唯一的无异议是:

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关键字不会“受益”? 是否有可能使其有效?

以上是由clang编译的:

-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

1 个答案:

答案 0 :(得分:1)

您需要阅读C标准中的规则。

&#34;限制&#34;指针当然可以是别名。它只是在某些情况下会产生未定义的行为,因此它们是别名,但完全允许编译器忽略它。

您还需要注意&#34;限制&#34;只影响派生自&#34;限制&#34;指针与指针保证不是从相同的&#34;限制&#34;指针。例如,如果p是&#34;限制&#34;指针,你调用f(p),该调用可以将p存储到任何静态或全局指针变量。因此,如果在调用之后读取这样的指针变量,编译器不知道它是否从限制指针派生,如果它是从p派生的,则应用别名规则。