What's the Alias Analysis does clang use ?

Hi, LLVM community:

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
for c/c++ keyword restrict.

let assume we compile the following code:
$cat myalias.cc

float foo(float * restrict v0, float * restrict v1, float * restrict v2, float * restrict t) {
float res;
for (int i=0; i<10; ++i) {
float x = v0[1];
float y = v1[1];
float z = v2[1];

res = x * 0.67 + y * 0.17 + z * 0.16;
t[i] = res;
}

return res;
}

$clang -emit-llvm -c myalias.cc -o myalias.bc

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.

$ opt -basicaa -licm -print-alias-sets myalias.bc -o myalias.opt.bc -stats -debug-only=licm
LICM hoisting to entry: %1 = load float** %v0.addr, align 8
LICM hoisting to entry: %arrayidx = getelementptr inbounds float* %0, i64 1
LICM hoisting to entry: %3 = load float** %v1.addr, align 8
LICM hoisting to entry: %arrayidx1 = getelementptr inbounds float* %1, i64 1
LICM hoisting to entry: %5 = load float** %v2.addr, align 8
LICM hoisting to entry: %arrayidx2 = getelementptr inbounds float* %2, i64 1
LICM hoisting to entry: %12 = load float** %t.addr, align 8
Alias Set Tracker: 10 alias sets for 13 pointer values.
AliasSet[0x1b7e800, 1] must alias, Mod/Ref Pointers: (float** %v0.addr, 8)
AliasSet[0x1b7d7e0, 1] must alias, Mod/Ref Pointers: (float** %v1.addr, 8)
AliasSet[0x1b7d8a0, 1] must alias, Mod/Ref Pointers: (float** %v2.addr, 8)
AliasSet[0x1b912e0, 1] must alias, Mod/Ref Pointers: (float** %t.addr, 8)
AliasSet[0x1b913a0, 1] must alias, Mod/Ref Pointers: (i32* %i, 4)
AliasSet[0x1b91510, 4] may alias, Mod/Ref Pointers: (float* %arrayidx, 4), (float* %arrayidx1, 4), (float* %arrayidx2, 4), (float* %arrayidx9, 4)
AliasSet[0x1b91590, 1] must alias, Mod/Ref Pointers: (float* %x, 4)
AliasSet[0x1b91690, 1] must alias, Mod/Ref Pointers: (float* %y, 4)
AliasSet[0x1b91790, 1] must alias, Mod/Ref Pointers: (float* %z, 4)
AliasSet[0x1b91850, 1] must alias, Mod/Ref Pointers: (float* %res, 4)

Hi,

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:

%v0.addr = alloca float*, align 8
%v1.addr = alloca float*, align 8
%v2.addr = alloca float*, align 8
%t.addr = alloca float*, align 8

...

store float* %v0, float** %v0.addr, align 8
store float* %v1, float** %v1.addr, align 8
store float* %v2, float** %v2.addr, align 8
store float* %t, float** %t.addr, align 8

If I had to guess, running -sroa (or -mem2reg) will clean this up for you.

Just in case you don't know, running:

opt -O2 -debug-pass=Arguments -S < /dev/null

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.

-Hal

Hi, Finkel

Thank you for heading up. using your approach, I can narrow down the following combo optimizes the good code.
opt -basicaa -mem2reg -loop-rotate -licm myalias.bc -o myalias.opt.bc -stats -debug-only=licm

further, I think scalar-evolution should be helpful to analyze loop indvar. it’s not good for my case.

thanks,
–lx