1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00
llvm-mirror/test/Transforms/LoopUnrollAndJam/disable.ll
David Green 3248675f42 [UnrollAndJam] New Unroll and Jam pass
This is a simple implementation of the unroll-and-jam classical loop
optimisation.

The basic idea is that we take an outer loop of the form:

  for i..
    ForeBlocks(i)
    for j..
      SubLoopBlocks(i, j)
    AftBlocks(i)

Instead of doing normal inner or outer unrolling, we unroll as follows:

  for i... i+=2
    ForeBlocks(i)
    ForeBlocks(i+1)
    for j..
      SubLoopBlocks(i, j)
      SubLoopBlocks(i+1, j)
    AftBlocks(i)
    AftBlocks(i+1)
  Remainder Loop

So we have unrolled the outer loop, then jammed the two inner loops into
one. This can lead to a simpler inner loop if memory accesses can be shared
between the now jammed loops.

To do this we have to prove that this is all safe, both for the memory
accesses (using dependence analysis) and that ForeBlocks(i+1) can move before
AftBlocks(i) and SubLoopBlocks(i, j).

Differential Revision: https://reviews.llvm.org/D41953

llvm-svn: 336062
2018-07-01 12:47:30 +00:00

742 lines
23 KiB
LLVM

; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam -unroll-and-jam-count=4 -pass-remarks=loop-unroll-and-jam < %s -S 2>&1 | FileCheck %s
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
;; Common check for all tests. None should be unroll and jammed
; CHECK-NOT: remark: {{.*}} unroll and jammed
; CHECK-LABEL: disabled1
; Tests for(i) { sum = A[i]; for(j) sum += B[j]; A[i+1] = sum; }
; A[i] to A[i+1] dependency should block unrollandjam
define void @disabled1(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i.029 = phi i32 [ %add10, %for.latch ], [ 0, %for.preheader ]
; CHECK: %j.026 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp127 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp127, %cmp
br i1 %or.cond, label %for.preheader, label %return
for.preheader:
br label %for.outer
for.outer:
%i.029 = phi i32 [ %add10, %for.latch ], [ 0, %for.preheader ]
%b.028 = phi i32 [ %inc8, %for.latch ], [ 1, %for.preheader ]
%arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.029
%0 = load i32, i32* %arrayidx, align 4
br label %for.inner
for.inner:
%j.026 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1.025 = phi i32 [ %0, %for.outer ], [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %B, i32 %j.026
%1 = load i32, i32* %arrayidx6, align 4
%add = add i32 %1, %sum1.025
%inc = add nuw i32 %j.026, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%arrayidx7 = getelementptr inbounds i32, i32* %A, i32 %b.028
store i32 %add, i32* %arrayidx7, align 4
%inc8 = add nuw nsw i32 %b.028, 1
%add10 = add nuw nsw i32 %i.029, 1
%exitcond30 = icmp eq i32 %add10, %I
br i1 %exitcond30, label %return, label %for.outer
return:
ret void
}
; CHECK-LABEL: disabled2
; Tests an incompatible block layout (for.outer jumps past for.inner)
; FIXME: Make this work
define void @disabled2(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i.032 = phi i32 [ %add13, %for.latch ], [ 0, %for.preheader ]
; CHECK: %j.030 = phi i32 [ %inc, %for.inner ], [ 0, %for.inner.preheader ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp131 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp131, %cmp
br i1 %or.cond, label %for.preheader, label %for.end14
for.preheader:
br label %for.outer
for.outer:
%i.032 = phi i32 [ %add13, %for.latch ], [ 0, %for.preheader ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %i.032
%0 = load i32, i32* %arrayidx, align 4
%tobool = icmp eq i32 %0, 0
br i1 %tobool, label %for.latch, label %for.inner
for.inner:
%j.030 = phi i32 [ %inc, %for.inner ], [ 0, %for.outer ]
%sum1.029 = phi i32 [ %sum1.1, %for.inner ], [ 0, %for.outer ]
%arrayidx6 = getelementptr inbounds i32, i32* %B, i32 %j.030
%1 = load i32, i32* %arrayidx6, align 4
%tobool7 = icmp eq i32 %1, 0
%sub = add i32 %sum1.029, 10
%add = sub i32 %sub, %1
%sum1.1 = select i1 %tobool7, i32 %sum1.029, i32 %add
%inc = add nuw i32 %j.030, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%sum1.1.lcssa = phi i32 [ 0, %for.outer ], [ %sum1.1, %for.inner ]
%arrayidx11 = getelementptr inbounds i32, i32* %A, i32 %i.032
store i32 %sum1.1.lcssa, i32* %arrayidx11, align 4
%add13 = add nuw i32 %i.032, 1
%exitcond33 = icmp eq i32 %add13, %I
br i1 %exitcond33, label %for.end14, label %for.outer
for.end14:
ret void
}
; CHECK-LABEL: disabled3
; Tests loop carry dependencies in an array S
define void @disabled3(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i.029 = phi i32 [ 0, %for.preheader ], [ %add12, %for.latch ]
; CHECK: %j.027 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%S = alloca [4 x i32], align 4
%cmp = icmp eq i32 %J, 0
br i1 %cmp, label %return, label %if.end
if.end:
%0 = bitcast [4 x i32]* %S to i8*
%cmp128 = icmp eq i32 %I, 0
br i1 %cmp128, label %for.cond.cleanup, label %for.preheader
for.preheader:
%arrayidx9 = getelementptr inbounds [4 x i32], [4 x i32]* %S, i32 0, i32 0
br label %for.outer
for.cond.cleanup:
br label %return
for.outer:
%i.029 = phi i32 [ 0, %for.preheader ], [ %add12, %for.latch ]
br label %for.inner
for.inner:
%j.027 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j.027
%l2 = load i32, i32* %arrayidx, align 4
%add = add i32 %j.027, %i.029
%rem = urem i32 %add, %J
%arrayidx6 = getelementptr inbounds i32, i32* %B, i32 %rem
%l3 = load i32, i32* %arrayidx6, align 4
%mul = mul i32 %l3, %l2
%rem7 = urem i32 %j.027, 3
%arrayidx8 = getelementptr inbounds [4 x i32], [4 x i32]* %S, i32 0, i32 %rem7
store i32 %mul, i32* %arrayidx8, align 4
%inc = add nuw i32 %j.027, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%l1 = load i32, i32* %arrayidx9, align 4
%arrayidx10 = getelementptr inbounds i32, i32* %A, i32 %i.029
store i32 %l1, i32* %arrayidx10, align 4
%add12 = add nuw i32 %i.029, 1
%exitcond31 = icmp eq i32 %add12, %I
br i1 %exitcond31, label %for.cond.cleanup, label %for.outer
return:
ret void
}
; CHECK-LABEL: disabled4
; Inner looop induction variable is not consistent
; ie for(i = 0..n) for (j = 0..i) sum+=B[j]
define void @disabled4(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %indvars.iv = phi i32 [ %indvars.iv.next, %for.latch ], [ 1, %for.preheader ]
; CHECK: %j.021 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ugt i32 %I, 1
%or.cond = and i1 %cmp122, %cmp
br i1 %or.cond, label %for.preheader, label %for.end9
for.preheader:
br label %for.outer
for.outer:
%indvars.iv = phi i32 [ %indvars.iv.next, %for.latch ], [ 1, %for.preheader ]
br label %for.inner
for.inner:
%j.021 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1.020 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j.021
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1.020
%inc = add nuw i32 %j.021, 1
%exitcond = icmp eq i32 %inc, %indvars.iv
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %indvars.iv
store i32 %add, i32* %arrayidx6, align 4
%indvars.iv.next = add nuw i32 %indvars.iv, 1
%exitcond24 = icmp eq i32 %indvars.iv.next, %I
br i1 %exitcond24, label %for.end9, label %for.outer
for.end9:
ret void
}
; CHECK-LABEL: disabled5
; Test odd uses of phi nodes where the outer IV cannot be moved into Fore as it hits a PHI
@f = hidden global i32 0, align 4
define i32 @disabled5() #0 {
; CHECK: %0 = phi i32 [ %f.promoted10, %entry ], [ 2, %for.latch ]
; CHECK: %1 = phi i32 [ %0, %for.outer ], [ 2, %for.inner ]
entry:
%f.promoted10 = load i32, i32* @f, align 4
br label %for.outer
for.outer:
%0 = phi i32 [ %f.promoted10, %entry ], [ 2, %for.latch ]
%d.018 = phi i16 [ 0, %entry ], [ %odd.lcssa, %for.latch ]
%inc5.sink9 = phi i32 [ 2, %entry ], [ %inc5, %for.latch ]
br label %for.inner
for.inner:
%1 = phi i32 [ %0, %for.outer ], [ 2, %for.inner ]
%inc.sink8 = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%inc = add nuw nsw i32 %inc.sink8, 1
%exitcond = icmp ne i32 %inc, 7
br i1 %exitcond, label %for.inner, label %for.latch
for.latch:
%.lcssa = phi i32 [ %1, %for.inner ]
%odd.lcssa = phi i16 [ 1, %for.inner ]
%inc5 = add nuw nsw i32 %inc5.sink9, 1
%exitcond11 = icmp ne i32 %inc5, 7
br i1 %exitcond11, label %for.outer, label %for.end
for.end:
%.lcssa.lcssa = phi i32 [ %.lcssa, %for.latch ]
%inc.lcssa.lcssa = phi i32 [ 7, %for.latch ]
ret i32 0
}
; CHECK-LABEL: disabled6
; There is a dependency in here, between @d and %0 (=@f)
@d6 = hidden global i16 5, align 2
@f6 = hidden global i16* @d6, align 4
define i32 @disabled6() #0 {
; CHECK: %inc8.sink14.i = phi i16 [ 1, %entry ], [ %inc8.i, %for.cond.cleanup.i ]
; CHECK: %c.013.i = phi i32 [ 0, %for.body.i ], [ %inc.i, %for.body6.i ]
entry:
store i16 1, i16* @d6, align 2
%0 = load i16*, i16** @f6, align 4
br label %for.body.i
for.body.i:
%inc8.sink14.i = phi i16 [ 1, %entry ], [ %inc8.i, %for.cond.cleanup.i ]
%1 = load i16, i16* %0, align 2
br label %for.body6.i
for.cond.cleanup.i:
%inc8.i = add nuw nsw i16 %inc8.sink14.i, 1
store i16 %inc8.i, i16* @d6, align 2
%cmp.i = icmp ult i16 %inc8.i, 6
br i1 %cmp.i, label %for.body.i, label %test.exit
for.body6.i:
%c.013.i = phi i32 [ 0, %for.body.i ], [ %inc.i, %for.body6.i ]
%inc.i = add nuw nsw i32 %c.013.i, 1
%exitcond.i = icmp eq i32 %inc.i, 7
br i1 %exitcond.i, label %for.cond.cleanup.i, label %for.body6.i
test.exit:
%conv2.i = sext i16 %1 to i32
ret i32 0
}
; CHECK-LABEL: disabled7
; Has negative output dependency
define void @disabled7(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i.028 = phi i32 [ %add11, %for.cond3.for.cond.cleanup5_crit_edge ], [ 0, %for.body.preheader ]
; CHECK: %j.026 = phi i32 [ 0, %for.body ], [ %add9, %for.body6 ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp127 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp127, %cmp
br i1 %or.cond, label %for.body.preheader, label %for.end12
for.body.preheader:
br label %for.body
for.body:
%i.028 = phi i32 [ %add11, %for.cond3.for.cond.cleanup5_crit_edge ], [ 0, %for.body.preheader ]
%arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.028
store i32 0, i32* %arrayidx, align 4
%sub = add i32 %i.028, -1
%arrayidx2 = getelementptr inbounds i32, i32* %A, i32 %sub
store i32 2, i32* %arrayidx2, align 4
br label %for.body6
for.cond3.for.cond.cleanup5_crit_edge:
store i32 %add, i32* %arrayidx, align 4
%add11 = add nuw i32 %i.028, 1
%exitcond29 = icmp eq i32 %add11, %I
br i1 %exitcond29, label %for.end12, label %for.body
for.body6:
%0 = phi i32 [ 0, %for.body ], [ %add, %for.body6 ]
%j.026 = phi i32 [ 0, %for.body ], [ %add9, %for.body6 ]
%arrayidx7 = getelementptr inbounds i32, i32* %B, i32 %j.026
%1 = load i32, i32* %arrayidx7, align 4
%add = add i32 %1, %0
%add9 = add nuw i32 %j.026, 1
%exitcond = icmp eq i32 %add9, %J
br i1 %exitcond, label %for.cond3.for.cond.cleanup5_crit_edge, label %for.body6
for.end12:
ret void
}
; CHECK-LABEL: disabled8
; Same as above with an extra outer loop nest
define void @disabled8(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i.036 = phi i32 [ %add15, %for.latch ], [ 0, %for.body ]
; CHECK: %j.034 = phi i32 [ 0, %for.outer ], [ %add13, %for.inner ]
entry:
%cmp = icmp eq i32 %J, 0
%cmp335 = icmp eq i32 %I, 0
%or.cond = or i1 %cmp, %cmp335
br i1 %or.cond, label %for.end18, label %for.body.preheader
for.body.preheader:
br label %for.body
for.body:
%x.037 = phi i32 [ %inc, %for.cond.cleanup4 ], [ 0, %for.body.preheader ]
br label %for.outer
for.cond.cleanup4:
%inc = add nuw nsw i32 %x.037, 1
%exitcond40 = icmp eq i32 %inc, 5
br i1 %exitcond40, label %for.end18, label %for.body
for.outer:
%i.036 = phi i32 [ %add15, %for.latch ], [ 0, %for.body ]
%arrayidx = getelementptr inbounds i32, i32* %A, i32 %i.036
store i32 0, i32* %arrayidx, align 4
%sub = add i32 %i.036, -1
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %sub
store i32 2, i32* %arrayidx6, align 4
br label %for.inner
for.latch:
store i32 %add, i32* %arrayidx, align 4
%add15 = add nuw i32 %i.036, 1
%exitcond38 = icmp eq i32 %add15, %I
br i1 %exitcond38, label %for.cond.cleanup4, label %for.outer
for.inner:
%0 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%j.034 = phi i32 [ 0, %for.outer ], [ %add13, %for.inner ]
%arrayidx11 = getelementptr inbounds i32, i32* %B, i32 %j.034
%1 = load i32, i32* %arrayidx11, align 4
%add = add i32 %1, %0
%add13 = add nuw i32 %j.034, 1
%exitcond = icmp eq i32 %add13, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.end18:
ret void
}
; CHECK-LABEL: disabled9
; Can't prove alias between A and B
define void @disabled9(i32 %I, i32 %J, i32* nocapture %A, i32* nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable10
; Simple call
declare void @f10(i32, i32) #0
define void @disable10(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
tail call void @f10(i32 %i, i32 %j) nounwind
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable11
; volatile
define void @disable11(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load volatile i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable12
; Multiple aft blocks
define void @disable12(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch3 ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch3 ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%cmpl = icmp eq i32 %add.lcssa, 10
br i1 %cmpl, label %for.latch2, label %for.latch3
for.latch2:
br label %for.latch3
for.latch3:
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable13
; Two subloops
define void @disable13(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
; CHECK: %j2 = phi i32 [ %inc2, %for.inner2 ], [ 0, %for.inner2.preheader ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.inner2, label %for.inner
for.inner2:
%j2 = phi i32 [ 0, %for.inner ], [ %inc2, %for.inner2 ]
%sum12 = phi i32 [ 0, %for.inner ], [ %add2, %for.inner2 ]
%arrayidx2 = getelementptr inbounds i32, i32* %B, i32 %j2
%l0 = load i32, i32* %arrayidx2, align 4
%add2 = add i32 %l0, %sum12
%inc2 = add nuw i32 %j2, 1
%exitcond2 = icmp eq i32 %inc2, %J
br i1 %exitcond2, label %for.latch, label %for.inner2
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner2 ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable14
; Multiple exits blocks
define void @disable14(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ %inc, %for.inner ], [ 0, %for.inner.preheader ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
%add8 = add nuw i32 %i, 1
%exitcond23 = icmp eq i32 %add8, %I
br i1 %exitcond23, label %for.end.loopexit, label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable15
; Latch != exit
define void @disable15(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ %inc, %for.inner ], [ 0, %for.inner.preheader ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
br i1 %exitcond25, label %for.end.loopexit, label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
br label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}
; CHECK-LABEL: disable16
; Cannot move other before inner loop
define void @disable16(i32 %I, i32 %J, i32* noalias nocapture %A, i32* noalias nocapture readonly %B) #0 {
; CHECK: %i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
; CHECK: %j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
entry:
%cmp = icmp ne i32 %J, 0
%cmp122 = icmp ne i32 %I, 0
%or.cond = and i1 %cmp, %cmp122
br i1 %or.cond, label %for.outer.preheader, label %for.end
for.outer.preheader:
br label %for.outer
for.outer:
%i = phi i32 [ %add8, %for.latch ], [ 0, %for.outer.preheader ]
%otherphi = phi i32 [ %other, %for.latch ], [ 0, %for.outer.preheader ]
br label %for.inner
for.inner:
%j = phi i32 [ 0, %for.outer ], [ %inc, %for.inner ]
%sum1 = phi i32 [ 0, %for.outer ], [ %add, %for.inner ]
%arrayidx = getelementptr inbounds i32, i32* %B, i32 %j
%0 = load i32, i32* %arrayidx, align 4
%add = add i32 %0, %sum1
%inc = add nuw i32 %j, 1
%exitcond = icmp eq i32 %inc, %J
br i1 %exitcond, label %for.latch, label %for.inner
for.latch:
%add.lcssa = phi i32 [ %add, %for.inner ]
%arrayidx6 = getelementptr inbounds i32, i32* %A, i32 %i
store i32 %add.lcssa, i32* %arrayidx6, align 4
%add8 = add nuw i32 %i, 1
%exitcond25 = icmp eq i32 %add8, %I
%loadarr = getelementptr inbounds i32, i32* %A, i32 %i
%load = load i32, i32* %arrayidx6, align 4
%other = add i32 %otherphi, %load
br i1 %exitcond25, label %for.end.loopexit, label %for.outer
for.end.loopexit:
br label %for.end
for.end:
ret void
}