Question about IndVarSimplify

Hi guys,

I am trying to use the indvars pass, but i don’t see any changes in the IL representation.

For this simple function

void init_array(int k)
{
int A[20];
for (int i=2; i<10; i++)
A[i] = 0;
}

i run clang test-simple.c -S -emit-llvm -o test.il and i obtain the following il representation

define void @init_array(i32 %k) nounwind {
entry:
%k.addr = alloca i32, align 4
%A = alloca [20 x i32], align 4
%i = alloca i32, align 4
store i32 %k, i32* %k.addr, align 4
store i32 2, i32* %i, align 4
br label %for.cond

for.cond: ; preds = %for.inc, %entry
%tmp = load i32* %i, align 4
%cmp = icmp slt i32 %tmp, 10
br i1 %cmp, label %for.body, label %for.end

for.body: ; preds = %for.cond
%tmp1 = load i32* %i, align 4
%arrayidx = getelementptr inbounds [20 x i32]* %A, i32 0, i32 %tmp1
store i32 0, i32* %arrayidx, align 4
br label %for.inc

for.inc: ; preds = %for.body
%tmp2 = load i32* %i, align 4
%inc = add nsw i32 %tmp2, 1
store i32 %inc, i32* %i, align 4
br label %for.cond

for.end: ; preds = %for.cond
ret void
}

Running opt -loop-simplify < test.il -S gives me the same output, which is what i would expect.
The problem is that running opt -indvars < test.il -S gives, again, the same output, but i would expect that i starts from 0 and is, eventualy, defined using a PHYNode.

What it’s wrong with what i’m doing?

Thank you.
Have a nice day

Sorin Baltateanu wrote:

Hi guys,

I am trying to use the indvars pass, but i don't see any changes in the
IL representation.

For this simple function

void init_array(int k)
{
     int A[20];
     for (int i=2; i<10; i++)
         A[i] = 0;
}

i run *clang test-simple.c -S -emit-llvm -o test.il*
and i obtain the following il representation

define void @init_array(i32 %k) nounwind {
entry:
   %k.addr = alloca i32, align 4
   %A = alloca [20 x i32], align 4
   %i = alloca i32, align 4
   store i32 %k, i32* %k.addr, align 4
   store i32 2, i32* %i, align 4
   br label %for.cond

for.cond: ; preds = %for.inc, %entry
   %tmp = load i32* %i, align 4
   %cmp = icmp slt i32 %tmp, 10
   br i1 %cmp, label %for.body, label %for.end

for.body: ; preds = %for.cond
   %tmp1 = load i32* %i, align 4
   %arrayidx = getelementptr inbounds [20 x i32]* %A, i32 0, i32 %tmp1
   store i32 0, i32* %arrayidx, align 4
   br label %for.inc

for.inc: ; preds = %for.body
   %tmp2 = load i32* %i, align 4
   %inc = add nsw i32 %tmp2, 1
   store i32 %inc, i32* %i, align 4
   br label %for.cond

for.end: ; preds = %for.cond
   ret void
}

Running *opt -loop-simplify < test.il <http://test.il> -S* gives me the
same output, which is what i would expect.
The problem is that running *opt -indvars < test.il <http://test.il> -S*
gives, again, the same output, but i would expect that i starts from 0
and is, eventualy, defined using a PHYNode.

What it's wrong with what i'm doing?

Each optimization pass in LLVM does one job only. Indvars does induction variable canonicalization, not SSA construction, so it sees those loads and stores and assumes they can't be optimized because they already would have been by other optimizers. SSA construction is done by -mem2reg. You can run opt -mem2reg -indvars, or just opt -mem2reg then opt -indvars individually to see what effect each has.

Nick

You aren't running a normal pass pipeline; in particular, not running
mem2reg/scalarrepl first prevents a lot of optimizations from working
as expected.

-Eli

Thanks. Works fine now and made some other things clear too.