<div dir="ltr">Hi, LLVM community:<div><br></div><div style>I found basicaa seems not to tell must-not-alias for __restrict__ arguments in c/c++. It only compares two pointers and the underlying objects they point to.  I wonder how clang does alias analysis </div>
<div style>for c/c++  keyword restrict.</div><div style><br></div><div style>let assume we compile the following code:</div><div style>$cat myalias.cc</div><div style><div>float foo(float * __restrict__ v0, float * __restrict__ v1, float * __restrict__ v2, float * __restrict__ t) {</div>
<div>        float res;</div><div>        for (int i=0; i<10; ++i) {</div><div>                float x = v0[1];</div><div>                float y = v1[1];</div><div>                float z = v2[1];</div><div><br></div>
<div>                res = x * 0.67 + y * 0.17 + z * 0.16;       </div><div>                t[i] = res;</div><div>        } </div><div>        </div><div>        </div><div>        return res;</div><div>}</div><div><br></div>
<div style>$clang -emit-llvm -c myalias.cc -o myalias.bc<br></div><div style>Clearly each argument has attribute 'noalias' in LLVM IR. I plan to use basicaa and licm to hoist all load/store of x/y/z and res to ahead of loop.  </div>
<div style><br></div><div><div>$ opt -basicaa  -licm   -print-alias-sets myalias.bc -o myalias.opt.bc -stats  -debug-only=licm</div><div>LICM hoisting to entry:   %1 = load float** %v0.addr, align 8</div><div>LICM hoisting to entry:   %arrayidx = getelementptr inbounds float* %0, i64 1</div>
<div>LICM hoisting to entry:   %3 = load float** %v1.addr, align 8</div><div>LICM hoisting to entry:   %arrayidx1 = getelementptr inbounds float* %1, i64 1</div><div>LICM hoisting to entry:   %5 = load float** %v2.addr, align 8</div>
<div>LICM hoisting to entry:   %arrayidx2 = getelementptr inbounds float* %2, i64 1</div><div>LICM hoisting to entry:   %12 = load float** %t.addr, align 8</div><div>Alias Set Tracker: 10 alias sets for 13 pointer values.</div>
<div>  AliasSet[0x1b7e800, 1] must alias, Mod/Ref   Pointers: (float** %v0.addr, 8)</div><div>  AliasSet[0x1b7d7e0, 1] must alias, Mod/Ref   Pointers: (float** %v1.addr, 8)</div><div>  AliasSet[0x1b7d8a0, 1] must alias, Mod/Ref   Pointers: (float** %v2.addr, 8)</div>
<div>  AliasSet[0x1b912e0, 1] must alias, Mod/Ref   Pointers: (float** %t.addr, 8)</div><div>  AliasSet[0x1b913a0, 1] must alias, Mod/Ref   Pointers: (i32* %i, 4)</div><div><span style="background-color:rgb(255,255,255)"><font color="#ff0000">  AliasSet[0x1b91510, 4] may alias, Mod/Ref   Pointers: (float* %arrayidx, 4), (float* %arrayidx1, 4), (float* %arrayidx2, 4), (float* %arrayidx9, 4)</font></span></div>
<div>  AliasSet[0x1b91590, 1] must alias, Mod/Ref   Pointers: (float* %x, 4)</div><div>  AliasSet[0x1b91690, 1] must alias, Mod/Ref   Pointers: (float* %y, 4)</div><div>  AliasSet[0x1b91790, 1] must alias, Mod/Ref   Pointers: (float* %z, 4)</div>
<div>  AliasSet[0x1b91850, 1] must alias, Mod/Ref   Pointers: (float* %res, 4)</div><div><br></div><div>===-------------------------------------------------------------------------===</div><div>                          ... Statistics Collected ...</div>
<div>===-------------------------------------------------------------------------===</div><div><br></div><div> 7 licm            - Number of instructions hoisted out of loop</div><div> 4 licm            - Number of load insts hoisted or sunk</div>
<div>32 memory-builtins - Number of load instructions with unsolved size and offset</div></div><div><br></div><div><br></div><div style>The result is not good.  The loop contains redundant computation. Clearly, Basicaa works out wrong AliasSet 'may alias' (arrayidx, arrayidx1, arrayidx2, arrayidx9). </div>
<div style>-tbaa doesn't help much here.  Because v0/v1, v2, and t are all have 'noalias' attributes. I think AA should know that %5,%6,%7 are loading from distinguishing locations </div><div style>and no instruction in loop body will modify those places. </div>
<div style><br></div><div style><div>; ModuleID = '<stdin>'</div><div>target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"</div>
<div>target triple = "x86_64-unknown-linux-gnu"</div><div><br></div><div>define float @_Z3fooPfS_S_S_(float* noalias %v0, float* noalias %v1, float* noalias %v2, float* noalias %t) nounwind uwtable {</div><div>entry:</div>
<div>  %v0.addr = alloca float*, align 8</div><div>  %v1.addr = alloca float*, align 8</div><div>  %v2.addr = alloca float*, align 8</div><div>  %t.addr = alloca float*, align 8</div><div>  %res = alloca float, align 4</div>
<div>  %i = alloca i32, align 4</div><div>  %x = alloca float, align 4</div><div>  %y = alloca float, align 4</div><div>  %z = alloca float, align 4</div><div>  store float* %v0, float** %v0.addr, align 8</div><div>  store float* %v1, float** %v1.addr, align 8</div>
<div>  store float* %v2, float** %v2.addr, align 8</div><div>  store float* %t, float** %t.addr, align 8</div><div>  store i32 0, i32* %i, align 4</div><div>  %0 = load float** %v0.addr, align 8</div><div>  %arrayidx = getelementptr inbounds float* %0, i64 1</div>
<div>  %1 = load float** %v1.addr, align 8</div><div>  %arrayidx1 = getelementptr inbounds float* %1, i64 1</div><div>  %2 = load float** %v2.addr, align 8</div><div>  %arrayidx2 = getelementptr inbounds float* %2, i64 1</div>
<div>  %3 = load float** %t.addr, align 8</div><div>  br label %for.cond</div><div><br></div><div>for.cond:                                         ; preds = %for.inc, %entry</div><div>  %4 = load i32* %i, align 4</div><div>
  %cmp = icmp slt i32 %4, 10</div><div>  br i1 %cmp, label %for.body, label %for.end</div><div><br></div><div>for.body:                                         ; preds = %for.cond</div><div><font color="#0000ff">  %5 = load float* %arrayidx, align 4</font></div>
<div><font color="#0000ff">  store float %5, float* %x, align 4</font></div><div><font color="#0000ff">  %6 = load float* %arrayidx1, align 4</font></div><div><font color="#0000ff">  store float %6, float* %y, align 4</font></div>
<div><font color="#0000ff">  %7 = load float* %arrayidx2, align 4</font></div><div><font color="#0000ff">  store float %7, float* %z, align 4</font></div><div>  %8 = load float* %x, align 4</div><div>  %conv = fpext float %8 to double</div>
<div>  %mul = fmul double %conv, 6.700000e-01</div><div>  %9 = load float* %y, align 4</div><div>  %conv3 = fpext float %9 to double</div><div>  %mul4 = fmul double %conv3, 1.700000e-01</div><div>  %add = fadd double %mul, %mul4</div>
<div>  %10 = load float* %z, align 4</div><div>  %conv5 = fpext float %10 to double</div><div>  %mul6 = fmul double %conv5, 1.600000e-01</div><div>  %add7 = fadd double %add, %mul6</div><div>  %conv8 = fptrunc double %add7 to float</div>
<div>  store float %conv8, float* %res, align 4</div><div>  %11 = load float* %res, align 4</div><div>  %12 = load i32* %i, align 4</div><div>  %idxprom = sext i32 %12 to i64</div><div>  %arrayidx9 = getelementptr inbounds float* %3, i64 %idxprom</div>
<div>  store float %11, float* %arrayidx9, align 4</div><div>  br label %for.inc</div><div><br></div><div>for.inc:                                          ; preds = %for.body</div><div>  %13 = load i32* %i, align 4</div>
<div>  %inc = add nsw i32 %13, 1</div><div>  store i32 %inc, i32* %i, align 4</div><div>  br label %for.cond</div><div><br></div><div>for.end:                                          ; preds = %for.cond</div><div>  %14 = load float* %res, align 4</div>
<div>  ret float %14</div><div>}</div><div><br></div><div style>ps: "opt -O2" works. O2 involves too many optimizations. I don't think the redundant elimination is attributed to AA & LICM. </div></div></div>
<div style><br></div><div style>thanks,</div><div style>--lx</div><div style><br></div></div>