<div dir="ltr">Hi, Finkel <div><br></div><div>Thank you for heading up.  using your approach, I can narrow down the following combo optimizes the good code. </div>
<div> opt  -basicaa  -mem2reg  -loop-rotate  -licm    myalias.bc  -o myalias.opt.bc -stats -debug-only=licm<br></div><div><br></div><div style>further, I think scalar-evolution should be helpful to analyze loop indvar.  it's not good for my case. </div>
<div style><br></div><div style>thanks,</div><div style>--lx</div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Nov 12, 2013 at 11:34 AM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
Your problem is that the function arguments, which are makes as noalias, are not being directly used as the base objects of the array accesses:<br>
<div class="im"><br>
> %v0.addr = alloca float*, align 8<br>
> %v1.addr = alloca float*, align 8<br>
> %v2.addr = alloca float*, align 8<br>
> %t.addr = alloca float*, align 8<br>
</div>...<br>
<div class="im">> store float* %v0, float** %v0.addr, align 8<br>
> store float* %v1, float** %v1.addr, align 8<br>
> store float* %v2, float** %v2.addr, align 8<br>
> store float* %t, float** %t.addr, align 8<br>
<br>
</div>If I had to guess, running -sroa (or -mem2reg) will clean this up for you.<br>
<br>
Just in case you don't know, running:<br>
<br>
opt -O2 -debug-pass=Arguments -S < /dev/null<br>
<br>
will give you a command line for opt, equivalent to -O2, with the passes named explicitly. This is helpful for investigating these kinds of questions.<br>
<br>
 -Hal<br>
<div><div class="h5"><br>
----- Original Message -----<br>
><br>
><br>
> Hi, LLVM community:<br>
><br>
><br>
> I found basicaa seems not to tell must-not-alias for __restrict__<br>
> arguments in c/c++. It only compares two pointers and the underlying<br>
> objects they point to. I wonder how clang does alias analysis<br>
> for c/c++ keyword restrict.<br>
><br>
><br>
> let assume we compile the following code:<br>
> $cat myalias.cc<br>
><br>
> float foo(float * __restrict__ v0, float * __restrict__ v1, float *<br>
> __restrict__ v2, float * __restrict__ t) {<br>
> float res;<br>
> for (int i=0; i<10; ++i) {<br>
> float x = v0[1];<br>
> float y = v1[1];<br>
> float z = v2[1];<br>
><br>
><br>
> res = x * 0.67 + y * 0.17 + z * 0.16;<br>
> t[i] = res;<br>
> }<br>
><br>
><br>
> return res;<br>
> }<br>
><br>
><br>
> $clang -emit-llvm -c myalias.cc -o myalias.bc<br>
><br>
> Clearly each argument has attribute 'noalias' in LLVM IR. I plan to<br>
> use basicaa and licm to hoist all load/store of x/y/z and res to<br>
> ahead of loop.<br>
><br>
><br>
><br>
> $ opt -basicaa -licm -print-alias-sets myalias.bc -o myalias.opt.bc<br>
> -stats -debug-only=licm<br>
> LICM hoisting to entry: %1 = load float** %v0.addr, align 8<br>
> LICM hoisting to entry: %arrayidx = getelementptr inbounds float* %0,<br>
> i64 1<br>
> LICM hoisting to entry: %3 = load float** %v1.addr, align 8<br>
> LICM hoisting to entry: %arrayidx1 = getelementptr inbounds float*<br>
> %1, i64 1<br>
> LICM hoisting to entry: %5 = load float** %v2.addr, align 8<br>
> LICM hoisting to entry: %arrayidx2 = getelementptr inbounds float*<br>
> %2, i64 1<br>
> LICM hoisting to entry: %12 = load float** %t.addr, align 8<br>
> Alias Set Tracker: 10 alias sets for 13 pointer values.<br>
> AliasSet[0x1b7e800, 1] must alias, Mod/Ref Pointers: (float**<br>
> %v0.addr, 8)<br>
> AliasSet[0x1b7d7e0, 1] must alias, Mod/Ref Pointers: (float**<br>
> %v1.addr, 8)<br>
> AliasSet[0x1b7d8a0, 1] must alias, Mod/Ref Pointers: (float**<br>
> %v2.addr, 8)<br>
> AliasSet[0x1b912e0, 1] must alias, Mod/Ref Pointers: (float**<br>
> %t.addr, 8)<br>
> AliasSet[0x1b913a0, 1] must alias, Mod/Ref Pointers: (i32* %i, 4)<br>
> AliasSet[0x1b91510, 4] may alias, Mod/Ref Pointers: (float*<br>
> %arrayidx, 4), (float* %arrayidx1, 4), (float* %arrayidx2, 4),<br>
> (float* %arrayidx9, 4)<br>
> AliasSet[0x1b91590, 1] must alias, Mod/Ref Pointers: (float* %x, 4)<br>
> AliasSet[0x1b91690, 1] must alias, Mod/Ref Pointers: (float* %y, 4)<br>
> AliasSet[0x1b91790, 1] must alias, Mod/Ref Pointers: (float* %z, 4)<br>
> AliasSet[0x1b91850, 1] must alias, Mod/Ref Pointers: (float* %res, 4)<br>
><br>
><br>
> ===-------------------------------------------------------------------------===<br>
> ... Statistics Collected ...<br>
> ===-------------------------------------------------------------------------===<br>
><br>
><br>
> 7 licm - Number of instructions hoisted out of loop<br>
> 4 licm - Number of load insts hoisted or sunk<br>
> 32 memory-builtins - Number of load instructions with unsolved size<br>
> and offset<br>
><br>
><br>
><br>
><br>
> The result is not good. The loop contains redundant computation.<br>
> Clearly, Basicaa works out wrong AliasSet 'may alias' (arrayidx,<br>
> arrayidx1, arrayidx2, arrayidx9).<br>
> -tbaa doesn't help much here. Because v0/v1, v2, and t are all have<br>
> 'noalias' attributes. I think AA should know that %5,%6,%7 are<br>
> loading from distinguishing locations<br>
> and no instruction in loop body will modify those places.<br>
><br>
><br>
><br>
> ; ModuleID = '<stdin>'<br>
> target datalayout =<br>
> "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"<br>
> target triple = "x86_64-unknown-linux-gnu"<br>
><br>
><br>
> define float @_Z3fooPfS_S_S_(float* noalias %v0, float* noalias %v1,<br>
> float* noalias %v2, float* noalias %t) nounwind uwtable {<br>
> entry:<br>
> %v0.addr = alloca float*, align 8<br>
> %v1.addr = alloca float*, align 8<br>
> %v2.addr = alloca float*, align 8<br>
> %t.addr = alloca float*, align 8<br>
> %res = alloca float, align 4<br>
> %i = alloca i32, align 4<br>
> %x = alloca float, align 4<br>
> %y = alloca float, align 4<br>
> %z = alloca float, align 4<br>
> store float* %v0, float** %v0.addr, align 8<br>
> store float* %v1, float** %v1.addr, align 8<br>
> store float* %v2, float** %v2.addr, align 8<br>
> store float* %t, float** %t.addr, align 8<br>
> store i32 0, i32* %i, align 4<br>
> %0 = load float** %v0.addr, align 8<br>
> %arrayidx = getelementptr inbounds float* %0, i64 1<br>
> %1 = load float** %v1.addr, align 8<br>
> %arrayidx1 = getelementptr inbounds float* %1, i64 1<br>
> %2 = load float** %v2.addr, align 8<br>
> %arrayidx2 = getelementptr inbounds float* %2, i64 1<br>
> %3 = load float** %t.addr, align 8<br>
> br label %for.cond<br>
><br>
><br>
> for.cond: ; preds = %for.inc, %entry<br>
> %4 = load i32* %i, align 4<br>
> %cmp = icmp slt i32 %4, 10<br>
> br i1 %cmp, label %for.body, label %for.end<br>
><br>
><br>
> for.body: ; preds = %for.cond<br>
> %5 = load float* %arrayidx, align 4<br>
> store float %5, float* %x, align 4<br>
> %6 = load float* %arrayidx1, align 4<br>
> store float %6, float* %y, align 4<br>
> %7 = load float* %arrayidx2, align 4<br>
> store float %7, float* %z, align 4<br>
> %8 = load float* %x, align 4<br>
> %conv = fpext float %8 to double<br>
> %mul = fmul double %conv, 6.700000e-01<br>
> %9 = load float* %y, align 4<br>
> %conv3 = fpext float %9 to double<br>
> %mul4 = fmul double %conv3, 1.700000e-01<br>
> %add = fadd double %mul, %mul4<br>
> %10 = load float* %z, align 4<br>
> %conv5 = fpext float %10 to double<br>
> %mul6 = fmul double %conv5, 1.600000e-01<br>
> %add7 = fadd double %add, %mul6<br>
> %conv8 = fptrunc double %add7 to float<br>
> store float %conv8, float* %res, align 4<br>
> %11 = load float* %res, align 4<br>
> %12 = load i32* %i, align 4<br>
> %idxprom = sext i32 %12 to i64<br>
> %arrayidx9 = getelementptr inbounds float* %3, i64 %idxprom<br>
> store float %11, float* %arrayidx9, align 4<br>
> br label %for.inc<br>
><br>
><br>
> for.inc: ; preds = %for.body<br>
> %13 = load i32* %i, align 4<br>
> %inc = add nsw i32 %13, 1<br>
> store i32 %inc, i32* %i, align 4<br>
> br label %for.cond<br>
><br>
><br>
> for.end: ; preds = %for.cond<br>
> %14 = load float* %res, align 4<br>
> ret float %14<br>
> }<br>
><br>
><br>
> ps: "opt -O2" works. O2 involves too many optimizations. I don't<br>
> think the redundant elimination is attributed to AA & LICM.<br>
><br>
><br>
> thanks,<br>
> --lx<br>
><br>
><br>
</div></div>> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
><br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br>
</font></span></blockquote></div><br></div>