[LLVMdev] Rewriting compare instructions to avoid materializing previous induction variable

Chad Rosier mcrosier at codeaurora.org
Thu Aug 28 09:38:59 PDT 2014


All,
I've noticed cases where LSR generates IR like the following:

for.cond:                                         ; preds = %for.body
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1    ;; i++
  %2 = add i64 %indvars.iv.next, -1                    ;; previous i for cmp
  %tmp = trunc i64 %2 to i32
  %cmp = icmp slt i32 %tmp, %0                         ;; i < e
  br i1 %cmp, label %for.body, label %for.end.loopexit

Basically, the comparison is happening after the induction variable is
incremented, so LSR derives the previous induction variable by subtracting
1.  (Without LSR we actually use a register to save the previous value of
the induction variable, so I think deriving the value from the incremented
induction variable is goodness; no need to keep a register live across
loop iterations).

For my test case (on AArch64), we generates assembly like this:

.LBB0_2:
        ldr     w12, [x10, x11, lsl #2]
        cbz     w12, .LBB0_4
        add     x11, x11, #1
        sub     w12, w11, #1
        cmp      w12, w9
        b.lt    .LBB0_2

However, I believe this is equivalent to:

.LBB0_2:
        ldr     w12, [x10, x11, lsl #2]
        cbz     w12, .LBB0_4
        add     x11, x11, #1
        cmp      w11, w9
        b.le    .LBB0_2

We transform the comparison from (i < e) -> (i+1 <= e), so that we don't
have to materialize the previous value of i.

If my assumptions are correct, my question is how should this be
implemented?  My first thought was to try something in CodeGenPrepare (as
LSR is run rather late), but I have limited experience with this pass. 
Alternatively, I think I could write this as an InstCombine, which I
believe will be called by the CodeGenPrepare pass.

Thoughts?

 Chad





More information about the llvm-dev mailing list