[LLVMdev] missing optimization for icmps in induction variables?

Sanjoy Das sanjoy at playingwithpointers.com
Thu Dec 18 12:31:57 PST 2014


Hi all,

I'm trying to get llvm to optimize away the %cmp to true in

define i32 @foo(i32* %array, i32* %length_ptr, i32 %init) {
 entry:
  %length = load i32* %length_ptr, !range !0
  %len.sub.1 = sub i32 %length, 1
  %upper = icmp slt i32 %init, %len.sub.1
  br i1 %upper, label %loop, label %exit

 loop:
  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]
  %civ.inc = add i32 %civ, 1
  %cmp = icmp slt i32 %civ.inc, %length
  br i1 %cmp, label %latch, label %break

 latch:
  store i32 0, i32* %array
  %check = icmp slt i32 %civ.inc, %len.sub.1
  br i1 %check, label %loop, label %break

 break:
  ret i32 %civ.inc

 exit:
  ret i32 42
}

!0 = !{i32 0, i32 2147483647}


One way to prove "%cmp == true" in two steps

 1. notice that since both on the backedge and entry, %civ is known to
    be less than %len.sub.1, which not i32_signed_max.  This means
    %civ.inc is an "add nsw".

 2. on both the entry and backedge, we know "%civ `slt` %len.sub.1".
    This implies "(%civ nsw+ 1) `slt` (%len.sub.1 nsw+ 1)" ==>
    "%civ.inc `slt` %len".

Currently neither of these happen (i.e. even if I make transformation
(1) manually, (2) does not kick in).

Is the above reasoning correct?  If it is, what is the right place to
add this logic to?  I'm thinking ScalarEvolution (so that this gets
picked up by SimplifyIndVar), but maybe there is a more idiomatic
place?  The case above is a simplified form of my real workload, which
involves smin and smax expressions; so the implementation has to be
easily generalizable to such cases.


Thanks,
-- Sanjoy



More information about the llvm-dev mailing list