aboutsummaryrefslogtreecommitdiffstats
path: root/test/Transforms/LoopStrengthReduce
diff options
context:
space:
mode:
authorShih-wei Liao <sliao@google.com>2010-02-10 11:10:31 -0800
committerShih-wei Liao <sliao@google.com>2010-02-10 11:10:31 -0800
commite264f62ca09a8f65c87a46d562a4d0f9ec5d457e (patch)
tree59e3d57ef656cef79afa708ae0a3daf25cd91fcf /test/Transforms/LoopStrengthReduce
downloadexternal_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.gz
external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.tar.bz2
external_llvm-e264f62ca09a8f65c87a46d562a4d0f9ec5d457e.zip
Check in LLVM r95781.
Diffstat (limited to 'test/Transforms/LoopStrengthReduce')
-rw-r--r--test/Transforms/LoopStrengthReduce/2005-08-15-AddRecIV.ll57
-rw-r--r--test/Transforms/LoopStrengthReduce/2005-08-17-OutOfLoopVariant.ll17
-rw-r--r--test/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll32
-rw-r--r--test/Transforms/LoopStrengthReduce/2007-04-23-UseIterator.ll71
-rw-r--r--test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll24
-rw-r--r--test/Transforms/LoopStrengthReduce/2008-08-13-CmpStride.ll31
-rw-r--r--test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll99
-rw-r--r--test/Transforms/LoopStrengthReduce/2008-09-09-Overflow.ll48
-rw-r--r--test/Transforms/LoopStrengthReduce/2009-01-13-nonconstant-stride-outside-loop.ll39
-rw-r--r--test/Transforms/LoopStrengthReduce/2009-02-09-ivs-different-sizes.ll33
-rw-r--r--test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll48
-rw-r--r--test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll130
-rw-r--r--test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll24
-rw-r--r--test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll26
-rw-r--r--test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-2.ll58
-rw-r--r--test/Transforms/LoopStrengthReduce/count-to-zero.ll42
-rw-r--r--test/Transforms/LoopStrengthReduce/dead-phi.ll21
-rw-r--r--test/Transforms/LoopStrengthReduce/dg.exp3
-rw-r--r--test/Transforms/LoopStrengthReduce/different-type-ivs.ll25
-rw-r--r--test/Transforms/LoopStrengthReduce/dont-hoist-simple-loop-constants.ll23
-rw-r--r--test/Transforms/LoopStrengthReduce/dont_insert_redundant_ops.ll36
-rw-r--r--test/Transforms/LoopStrengthReduce/dont_reduce_bytes.ll22
-rw-r--r--test/Transforms/LoopStrengthReduce/dont_reverse.ll21
-rw-r--r--test/Transforms/LoopStrengthReduce/exit_compare_live_range.ll21
-rw-r--r--test/Transforms/LoopStrengthReduce/invariant_value_first.ll23
-rw-r--r--test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll20
-rw-r--r--test/Transforms/LoopStrengthReduce/nested-reduce.ll49
-rw-r--r--test/Transforms/LoopStrengthReduce/ops_after_indvar.ll24
-rw-r--r--test/Transforms/LoopStrengthReduce/phi_node_update_multiple_preds.ll28
-rw-r--r--test/Transforms/LoopStrengthReduce/pr2537.ll21
-rw-r--r--test/Transforms/LoopStrengthReduce/pr2570.ll287
-rw-r--r--test/Transforms/LoopStrengthReduce/pr3086.ll29
-rw-r--r--test/Transforms/LoopStrengthReduce/pr3399.ll32
-rw-r--r--test/Transforms/LoopStrengthReduce/pr3571.ll27
-rw-r--r--test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll18
-rw-r--r--test/Transforms/LoopStrengthReduce/related_indvars.ll27
-rw-r--r--test/Transforms/LoopStrengthReduce/remove_indvar.ll19
-rw-r--r--test/Transforms/LoopStrengthReduce/share_code_in_preheader.ll27
-rw-r--r--test/Transforms/LoopStrengthReduce/share_ivs.ll24
-rw-r--r--test/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll29
-rw-r--r--test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll41
-rw-r--r--test/Transforms/LoopStrengthReduce/variable_stride.ll18
42 files changed, 1694 insertions, 0 deletions
diff --git a/test/Transforms/LoopStrengthReduce/2005-08-15-AddRecIV.ll b/test/Transforms/LoopStrengthReduce/2005-08-15-AddRecIV.ll
new file mode 100644
index 0000000000..1f08a4367b
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2005-08-15-AddRecIV.ll
@@ -0,0 +1,57 @@
+; RUN: opt < %s -loop-reduce -disable-output
+
+define void @try_swap() {
+entry:
+ br i1 false, label %cond_continue.0.i, label %cond_false.0.i
+cond_false.0.i: ; preds = %entry
+ ret void
+cond_continue.0.i: ; preds = %entry
+ br i1 false, label %cond_continue.1.i, label %cond_false.1.i
+cond_false.1.i: ; preds = %cond_continue.0.i
+ ret void
+cond_continue.1.i: ; preds = %cond_continue.0.i
+ br i1 false, label %endif.3.i, label %else.0.i
+endif.3.i: ; preds = %cond_continue.1.i
+ br i1 false, label %my_irand.exit82, label %endif.0.i62
+else.0.i: ; preds = %cond_continue.1.i
+ ret void
+endif.0.i62: ; preds = %endif.3.i
+ ret void
+my_irand.exit82: ; preds = %endif.3.i
+ br i1 false, label %else.2, label %then.4
+then.4: ; preds = %my_irand.exit82
+ ret void
+else.2: ; preds = %my_irand.exit82
+ br i1 false, label %find_affected_nets.exit, label %loopentry.1.i107.outer.preheader
+loopentry.1.i107.outer.preheader: ; preds = %else.2
+ ret void
+find_affected_nets.exit: ; preds = %else.2
+ br i1 false, label %save_region_occ.exit, label %loopentry.1
+save_region_occ.exit: ; preds = %find_affected_nets.exit
+ br i1 false, label %no_exit.1.preheader, label %loopexit.1
+loopentry.1: ; preds = %find_affected_nets.exit
+ ret void
+no_exit.1.preheader: ; preds = %save_region_occ.exit
+ ret void
+loopexit.1: ; preds = %save_region_occ.exit
+ br i1 false, label %then.10, label %loopentry.3
+then.10: ; preds = %loopexit.1
+ ret void
+loopentry.3: ; preds = %endif.16, %loopexit.1
+ %indvar342 = phi i32 [ %indvar.next343, %endif.16 ], [ 0, %loopexit.1 ] ; <i32> [#uses=2]
+ br i1 false, label %loopexit.3, label %endif.16
+endif.16: ; preds = %loopentry.3
+ %indvar.next343 = add i32 %indvar342, 1 ; <i32> [#uses=1]
+ br label %loopentry.3
+loopexit.3: ; preds = %loopentry.3
+ br label %loopentry.4
+loopentry.4: ; preds = %loopentry.4, %loopexit.3
+ %indvar340 = phi i32 [ 0, %loopexit.3 ], [ %indvar.next341, %loopentry.4 ] ; <i32> [#uses=2]
+ %tmp. = add i32 %indvar340, %indvar342 ; <i32> [#uses=1]
+ %tmp.526 = load i32** null ; <i32*> [#uses=1]
+ %gep.upgrd.1 = zext i32 %tmp. to i64 ; <i64> [#uses=1]
+ %tmp.528 = getelementptr i32* %tmp.526, i64 %gep.upgrd.1 ; <i32*> [#uses=1]
+ store i32 0, i32* %tmp.528
+ %indvar.next341 = add i32 %indvar340, 1 ; <i32> [#uses=1]
+ br label %loopentry.4
+}
diff --git a/test/Transforms/LoopStrengthReduce/2005-08-17-OutOfLoopVariant.ll b/test/Transforms/LoopStrengthReduce/2005-08-17-OutOfLoopVariant.ll
new file mode 100644
index 0000000000..f1c523ae6c
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2005-08-17-OutOfLoopVariant.ll
@@ -0,0 +1,17 @@
+; RUN: opt < %s -loop-reduce -disable-output
+
+define i32 @image_to_texture(i32 %indvar454) {
+loopentry.1.outer:
+ %j.2.1.ph = bitcast i32 %indvar454 to i32 ; <i32> [#uses=1]
+ br label %loopentry.1
+loopentry.1: ; preds = %loopentry.1, %loopentry.1.outer
+ %i.3 = phi i32 [ 0, %loopentry.1.outer ], [ %i.3.be, %loopentry.1 ] ; <i32> [#uses=2]
+ %tmp.390 = load i32* null ; <i32> [#uses=1]
+ %tmp.392 = mul i32 %tmp.390, %j.2.1.ph ; <i32> [#uses=1]
+ %tmp.394 = add i32 %tmp.392, %i.3 ; <i32> [#uses=1]
+ %i.3.be = add i32 %i.3, 1 ; <i32> [#uses=1]
+ br i1 false, label %loopentry.1, label %label.6
+label.6: ; preds = %loopentry.1
+ ret i32 %tmp.394
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll b/test/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll
new file mode 100644
index 0000000000..f56a55379c
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll
@@ -0,0 +1,32 @@
+; RUN: opt < %s -loop-reduce -disable-output
+
+define void @main() {
+entry:
+ br label %loopentry.0
+loopentry.0: ; preds = %then.5, %entry
+ %arg_index.1.ph = phi i32 [ 1, %entry ], [ %arg_index.1.ph.be, %then.5 ] ; <i32> [#uses=1]
+ br i1 false, label %no_exit.0, label %loopexit.0
+no_exit.0: ; preds = %loopentry.0
+ %arg_index.1.1 = add i32 0, %arg_index.1.ph ; <i32> [#uses=2]
+ br i1 false, label %then.i55, label %endif.i61
+then.i55: ; preds = %no_exit.0
+ br i1 false, label %then.4, label %else.1
+endif.i61: ; preds = %no_exit.0
+ ret void
+then.4: ; preds = %then.i55
+ %tmp.19993 = add i32 %arg_index.1.1, 2 ; <i32> [#uses=0]
+ ret void
+else.1: ; preds = %then.i55
+ br i1 false, label %then.i86, label %loopexit.i97
+then.i86: ; preds = %else.1
+ ret void
+loopexit.i97: ; preds = %else.1
+ br i1 false, label %then.5, label %else.2
+then.5: ; preds = %loopexit.i97
+ %arg_index.1.ph.be = add i32 %arg_index.1.1, 2 ; <i32> [#uses=1]
+ br label %loopentry.0
+else.2: ; preds = %loopexit.i97
+ ret void
+loopexit.0: ; preds = %loopentry.0
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/2007-04-23-UseIterator.ll b/test/Transforms/LoopStrengthReduce/2007-04-23-UseIterator.ll
new file mode 100644
index 0000000000..8c2cfaf321
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2007-04-23-UseIterator.ll
@@ -0,0 +1,71 @@
+; RUN: opt < %s -loop-reduce -disable-output
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
+
+target triple = "i686-apple-darwin9"
+
+define i8* @foo( i8* %ABC) {
+entry:
+ switch i8 0, label %bb129 [
+ i8 0, label %UnifiedReturnBlock
+ i8 9, label %UnifiedReturnBlock
+ i8 32, label %UnifiedReturnBlock
+ i8 35, label %UnifiedReturnBlock
+ i8 37, label %bb16.preheader
+ ]
+
+bb16.preheader: ; preds = %entry
+ br label %bb16
+
+bb16: ; preds = %cond_next102, %bb16.preheader
+ %indvar = phi i32 [ %indvar.next, %cond_next102 ], [ 0, %bb16.preheader ] ; <i32> [#uses=2]
+ %ABC.2146.0.rec = mul i32 %indvar, 3 ; <i32> [#uses=1]
+ br i1 false, label %UnifiedReturnBlock.loopexit, label %cond_next102
+
+cond_next102: ; preds = %bb16
+ %tmp138145.rec = add i32 %ABC.2146.0.rec, 3 ; <i32> [#uses=1]
+ %tmp138145 = getelementptr i8* %ABC, i32 %tmp138145.rec ; <i8*> [#uses=4]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ switch i8 0, label %bb129.loopexit [
+ i8 0, label %UnifiedReturnBlock.loopexit
+ i8 9, label %UnifiedReturnBlock.loopexit
+ i8 32, label %UnifiedReturnBlock.loopexit
+ i8 35, label %UnifiedReturnBlock.loopexit
+ i8 37, label %bb16
+ ]
+
+bb129.loopexit: ; preds = %cond_next102
+ br label %bb129
+
+bb129: ; preds = %bb129.loopexit, %entry
+ ret i8* null
+
+UnifiedReturnBlock.loopexit: ; preds = %cond_next102, %cond_next102, %cond_next102, %cond_next102, %bb16
+ %UnifiedRetVal.ph = phi i8* [ %tmp138145, %cond_next102 ], [ %tmp138145, %cond_next102 ], [ %tmp138145, %cond_next102 ], [ %tmp138145, %cond_next102 ], [ null, %bb16 ] ; <i8*> [#uses=0]
+ br label %UnifiedReturnBlock
+
+UnifiedReturnBlock: ; preds = %UnifiedReturnBlock.loopexit, %entry, %entry, %entry, %entry
+ ret i8* null
+}
+
+define i8* @bar() {
+entry:
+ switch i8 0, label %bb158 [
+ i8 37, label %bb74
+ i8 58, label %cond_true
+ i8 64, label %bb11
+ ]
+
+bb11: ; preds = %entry
+ ret i8* null
+
+cond_true: ; preds = %entry
+ ret i8* null
+
+bb74: ; preds = %entry
+ ret i8* null
+
+bb158: ; preds = %entry
+ ret i8* null
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll b/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll
new file mode 100644
index 0000000000..7c7a21c013
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll
@@ -0,0 +1,24 @@
+; RUN: opt < %s -loop-reduce -S | grep ugt
+; PR2535
+
+@.str = internal constant [4 x i8] c"%d\0A\00"
+
+declare i32 @printf(i8* noalias , ...) nounwind
+
+define i32 @main() nounwind {
+entry:
+ br label %forbody
+
+forbody:
+ %i.0 = phi i32 [ 0, %entry ], [ %inc, %forbody ] ; <i32>[#uses=3]
+ %sub14 = sub i32 1027, %i.0 ; <i32> [#uses=1]
+ %mul15 = mul i32 %sub14, 10 ; <i32> [#uses=1]
+ %add166 = or i32 %mul15, 1 ; <i32> [#uses=1] *
+ call i32 (i8*, ...)* @printf( i8* noalias getelementptr ([4 x i8]* @.str, i32 0, i32 0), i32 %add166 ) nounwind
+ %inc = add i32 %i.0, 1 ; <i32> [#uses=3]
+ %cmp = icmp ult i32 %inc, 1027 ; <i1> [#uses=1]
+ br i1 %cmp, label %forbody, label %afterfor
+
+afterfor: ; preds = %forcond
+ ret i32 0
+}
diff --git a/test/Transforms/LoopStrengthReduce/2008-08-13-CmpStride.ll b/test/Transforms/LoopStrengthReduce/2008-08-13-CmpStride.ll
new file mode 100644
index 0000000000..90477d1069
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2008-08-13-CmpStride.ll
@@ -0,0 +1,31 @@
+; RUN: opt < %s -loop-reduce -S | grep add | count 2
+; PR 2662
+@g_3 = common global i16 0 ; <i16*> [#uses=2]
+@"\01LC" = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=1]
+
+define void @func_1() nounwind {
+entry:
+ br label %bb
+
+bb: ; preds = %bb, %entry
+ %l_2.0.reg2mem.0 = phi i16 [ 0, %entry ], [ %t1, %bb ] ; <i16> [#uses=2]
+ %t0 = shl i16 %l_2.0.reg2mem.0, 1 ; <i16>:0 [#uses=1]
+ volatile store i16 %t0, i16* @g_3, align 2
+ %t1 = add i16 %l_2.0.reg2mem.0, -3 ; <i16>:1 [#uses=2]
+ %t2 = icmp slt i16 %t1, 1 ; <i1>:2 [#uses=1]
+ br i1 %t2, label %bb, label %return
+
+return: ; preds = %bb
+ ret void
+}
+
+define i32 @main() nounwind {
+entry:
+ tail call void @func_1( ) nounwind
+ volatile load i16* @g_3, align 2 ; <i16>:0 [#uses=1]
+ zext i16 %0 to i32 ; <i32>:1 [#uses=1]
+ tail call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), i32 %1 ) nounwind ; <i32>:2 [#uses=0]
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...) nounwind
diff --git a/test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll b/test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll
new file mode 100644
index 0000000000..c650d8cf76
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll
@@ -0,0 +1,99 @@
+; RUN: opt < %s -loop-reduce -S | grep "phi double" | count 1
+
+define void @foobar(i32 %n) nounwind {
+entry:
+ icmp eq i32 %n, 0 ; <i1>:0 [#uses=2]
+ br i1 %0, label %return, label %bb.nph
+
+bb.nph: ; preds = %entry
+ %umax = select i1 %0, i32 1, i32 %n ; <i32> [#uses=1]
+ br label %bb
+
+bb: ; preds = %bb, %bb.nph
+ %i.03 = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; <i32> [#uses=3]
+ tail call void @bar( i32 %i.03 ) nounwind
+ uitofp i32 %i.03 to double ; <double>:1 [#uses=1]
+ tail call void @foo( double %1 ) nounwind
+ %indvar.next = add i32 %i.03, 1 ; <i32> [#uses=2]
+ %exitcond = icmp eq i32 %indvar.next, %umax ; <i1> [#uses=1]
+ br i1 %exitcond, label %return, label %bb
+
+return: ; preds = %bb, %entry
+ ret void
+}
+
+; Unable to eliminate cast because the mantissa bits for double are not enough
+; to hold all of i64 IV bits.
+define void @foobar2(i64 %n) nounwind {
+entry:
+ icmp eq i64 %n, 0 ; <i1>:0 [#uses=2]
+ br i1 %0, label %return, label %bb.nph
+
+bb.nph: ; preds = %entry
+ %umax = select i1 %0, i64 1, i64 %n ; <i64> [#uses=1]
+ br label %bb
+
+bb: ; preds = %bb, %bb.nph
+ %i.03 = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; <i64> [#uses=3]
+ trunc i64 %i.03 to i32 ; <i32>:1 [#uses=1]
+ tail call void @bar( i32 %1 ) nounwind
+ uitofp i64 %i.03 to double ; <double>:2 [#uses=1]
+ tail call void @foo( double %2 ) nounwind
+ %indvar.next = add i64 %i.03, 1 ; <i64> [#uses=2]
+ %exitcond = icmp eq i64 %indvar.next, %umax ; <i1> [#uses=1]
+ br i1 %exitcond, label %return, label %bb
+
+return: ; preds = %bb, %entry
+ ret void
+}
+
+; Unable to eliminate cast due to potentional overflow.
+define void @foobar3() nounwind {
+entry:
+ tail call i32 (...)* @nn( ) nounwind ; <i32>:0 [#uses=1]
+ icmp eq i32 %0, 0 ; <i1>:1 [#uses=1]
+ br i1 %1, label %return, label %bb
+
+bb: ; preds = %bb, %entry
+ %i.03 = phi i32 [ 0, %entry ], [ %3, %bb ] ; <i32> [#uses=3]
+ tail call void @bar( i32 %i.03 ) nounwind
+ uitofp i32 %i.03 to double ; <double>:2 [#uses=1]
+ tail call void @foo( double %2 ) nounwind
+ add i32 %i.03, 1 ; <i32>:3 [#uses=2]
+ tail call i32 (...)* @nn( ) nounwind ; <i32>:4 [#uses=1]
+ icmp ugt i32 %4, %3 ; <i1>:5 [#uses=1]
+ br i1 %5, label %bb, label %return
+
+return: ; preds = %bb, %entry
+ ret void
+}
+
+; Unable to eliminate cast due to overflow.
+define void @foobar4() nounwind {
+entry:
+ br label %bb.nph
+
+bb.nph: ; preds = %entry
+ br label %bb
+
+bb: ; preds = %bb, %bb.nph
+ %i.03 = phi i8 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; <i32> [#uses=3]
+ %tmp2 = sext i8 %i.03 to i32 ; <i32>:0 [#uses=1]
+ tail call void @bar( i32 %tmp2 ) nounwind
+ %tmp3 = uitofp i8 %i.03 to double ; <double>:1 [#uses=1]
+ tail call void @foo( double %tmp3 ) nounwind
+ %indvar.next = add i8 %i.03, 1 ; <i32> [#uses=2]
+ %tmp = sext i8 %indvar.next to i32
+ %exitcond = icmp eq i32 %tmp, 32767 ; <i1> [#uses=1]
+ br i1 %exitcond, label %return, label %bb
+
+return: ; preds = %bb, %entry
+ ret void
+}
+
+declare void @bar(i32)
+
+declare void @foo(double)
+
+declare i32 @nn(...)
+
diff --git a/test/Transforms/LoopStrengthReduce/2008-09-09-Overflow.ll b/test/Transforms/LoopStrengthReduce/2008-09-09-Overflow.ll
new file mode 100644
index 0000000000..1ee6b5cdf1
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2008-09-09-Overflow.ll
@@ -0,0 +1,48 @@
+; RUN: opt < %s -loop-reduce -S | grep phi | count 2
+; PR 2779
+@g_19 = common global i32 0 ; <i32*> [#uses=3]
+@"\01LC" = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=1]
+
+define i32 @func_8(i8 zeroext %p_9) nounwind {
+entry:
+ ret i32 1
+}
+
+define i32 @func_3(i8 signext %p_5) nounwind {
+entry:
+ ret i32 1
+}
+
+define void @func_1() nounwind {
+entry:
+ br label %bb
+
+bb: ; preds = %bb, %entry
+ %indvar = phi i16 [ 0, %entry ], [ %indvar.next, %bb ] ; <i16> [#uses=2]
+ %tmp = sub i16 0, %indvar ; <i16> [#uses=1]
+ %tmp27 = trunc i16 %tmp to i8 ; <i8> [#uses=1]
+ load i32* @g_19, align 4 ; <i32>:0 [#uses=2]
+ add i32 %0, 1 ; <i32>:1 [#uses=1]
+ store i32 %1, i32* @g_19, align 4
+ trunc i32 %0 to i8 ; <i8>:2 [#uses=1]
+ tail call i32 @func_8( i8 zeroext %2 ) nounwind ; <i32>:3 [#uses=0]
+ shl i8 %tmp27, 2 ; <i8>:4 [#uses=1]
+ add i8 %4, -112 ; <i8>:5 [#uses=1]
+ tail call i32 @func_3( i8 signext %5 ) nounwind ; <i32>:6 [#uses=0]
+ %indvar.next = add i16 %indvar, 1 ; <i16> [#uses=2]
+ %exitcond = icmp eq i16 %indvar.next, -28 ; <i1> [#uses=1]
+ br i1 %exitcond, label %return, label %bb
+
+return: ; preds = %bb
+ ret void
+}
+
+define i32 @main() nounwind {
+entry:
+ tail call void @func_1( ) nounwind
+ load i32* @g_19, align 4 ; <i32>:0 [#uses=1]
+ tail call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]* @"\01LC", i32 0, i32 0), i32 %0 ) nounwind ; <i32>:1 [#uses=0]
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...) nounwind
diff --git a/test/Transforms/LoopStrengthReduce/2009-01-13-nonconstant-stride-outside-loop.ll b/test/Transforms/LoopStrengthReduce/2009-01-13-nonconstant-stride-outside-loop.ll
new file mode 100644
index 0000000000..b2cf818dc4
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2009-01-13-nonconstant-stride-outside-loop.ll
@@ -0,0 +1,39 @@
+; RUN: opt < %s -loop-reduce -S | grep phi | count 1
+; RUN: opt < %s -loop-reduce -S | grep mul | count 1
+; ModuleID = '<stdin>'
+; Make sure examining a fuller expression outside the loop doesn't cause us to create a second
+; IV of stride %3.
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.5"
+ %struct.anon = type { %struct.obj*, %struct.obj* }
+ %struct.obj = type { i16, i16, { %struct.anon } }
+@heap_size = external global i32 ; <i32*> [#uses=1]
+@"\01LC85" = external constant [39 x i8] ; <[39 x i8]*> [#uses=1]
+
+declare i32 @sprintf(i8*, i8*, ...) nounwind
+
+define %struct.obj* @gc_status(%struct.obj* %args) nounwind {
+entry:
+ br label %bb1.i
+
+bb.i2: ; preds = %bb2.i3
+ %indvar.next24 = add i32 %m.0.i, 1 ; <i32> [#uses=1]
+ br label %bb1.i
+
+bb1.i: ; preds = %bb.i2, %entry
+ %m.0.i = phi i32 [ 0, %entry ], [ %indvar.next24, %bb.i2 ] ; <i32> [#uses=4]
+ %0 = icmp slt i32 %m.0.i, 0 ; <i1> [#uses=1]
+ br i1 %0, label %bb2.i3, label %nactive_heaps.exit
+
+bb2.i3: ; preds = %bb1.i
+ %1 = load %struct.obj** null, align 4 ; <%struct.obj*> [#uses=1]
+ %2 = icmp eq %struct.obj* %1, null ; <i1> [#uses=1]
+ br i1 %2, label %nactive_heaps.exit, label %bb.i2
+
+nactive_heaps.exit: ; preds = %bb2.i3, %bb1.i
+ %3 = load i32* @heap_size, align 4 ; <i32> [#uses=1]
+ %4 = mul i32 %3, %m.0.i ; <i32> [#uses=1]
+ %5 = sub i32 %4, 0 ; <i32> [#uses=1]
+ %6 = tail call i32 (i8*, i8*, ...)* @sprintf(i8* null, i8* getelementptr ([39 x i8]* @"\01LC85", i32 0, i32 0), i32 %m.0.i, i32 0, i32 %5, i32 0) nounwind ; <i32> [#uses=0]
+ ret %struct.obj* null
+}
diff --git a/test/Transforms/LoopStrengthReduce/2009-02-09-ivs-different-sizes.ll b/test/Transforms/LoopStrengthReduce/2009-02-09-ivs-different-sizes.ll
new file mode 100644
index 0000000000..36cc535451
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2009-02-09-ivs-different-sizes.ll
@@ -0,0 +1,33 @@
+; RUN: llc < %s
+; This used to crash.
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+target datalayout ="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @parse_number(i8* nocapture %p) nounwind {
+entry:
+ %shift.0 = select i1 false, i32 4, i32 2 ; <i32> [#uses=1]
+ br label %bb47
+
+bb47: ; preds = %bb47, %entry
+ br i1 false, label %bb54, label %bb47
+
+bb54: ; preds = %bb47
+ br i1 false, label %bb56, label %bb66
+
+bb56: ; preds = %bb62, %bb54
+ %p_addr.0.pn.rec = phi i64 [ %p_addr.6.rec, %bb62 ], [ 0, %bb54 ] ; <i64> [#uses=2]
+ %ch.6.in.in = phi i8* [ %p_addr.6, %bb62 ], [ null, %bb54 ] ; <i8*> [#uses=0]
+ %indvar202 = trunc i64 %p_addr.0.pn.rec to i32 ; <i32>[#uses=1]
+ %frac_bits.0 = mul i32 %indvar202, %shift.0 ; <i32>[#uses=1]
+ %p_addr.6.rec = add i64 %p_addr.0.pn.rec, 1 ; <i64>[#uses=2]
+ %p_addr.6 = getelementptr i8* null, i64 %p_addr.6.rec ; <i8*>[#uses=1]
+ br i1 false, label %bb66, label %bb62
+
+bb62: ; preds = %bb56
+ br label %bb56
+
+bb66: ; preds = %bb56, %bb54
+ %frac_bits.1 = phi i32 [ 0, %bb54 ], [ %frac_bits.0, %bb56 ] ; <i32> [#uses=0]
+ unreachable
+}
diff --git a/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll b/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll
new file mode 100644
index 0000000000..002a878b7b
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll
@@ -0,0 +1,48 @@
+; RUN: opt < %s -loop-reduce -S | FileCheck %s
+
+; The multiply in bb2 must not be reduced to an add, as the sext causes the
+; %1 argument to become negative after a while.
+
+; CHECK: sext i8
+; CHECK: mul i32
+; CHECK: store i32
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin9.6"
+@table = common global [32 x [256 x i32]] zeroinitializer, align 32 ; <[32 x [256 x i32]]*> [#uses=2]
+
+define i32 @main() nounwind {
+bb4.thread:
+ br label %bb2
+
+bb2: ; preds = %bb4, %bb2, %bb4.thread
+ %i.0.reg2mem.0.ph = phi i32 [ 0, %bb4.thread ], [ %i.0.reg2mem.0.ph, %bb2 ], [ %indvar.next9, %bb4 ] ; <i32> [#uses=4]
+ %j.0.reg2mem.0 = phi i32 [ 0, %bb4.thread ], [ %indvar.next, %bb2 ], [ 0, %bb4 ] ; <i32> [#uses=3]
+ %0 = trunc i32 %j.0.reg2mem.0 to i8 ; <i8> [#uses=1]
+ %1 = sext i8 %0 to i32 ; <i32> [#uses=1]
+ %2 = mul i32 %1, %i.0.reg2mem.0.ph ; <i32> [#uses=1]
+ %3 = getelementptr [32 x [256 x i32]]* @table, i32 0, i32 %i.0.reg2mem.0.ph, i32 %j.0.reg2mem.0 ; <i32*> [#uses=1]
+ store i32 %2, i32* %3, align 4
+ %indvar.next = add i32 %j.0.reg2mem.0, 1 ; <i32> [#uses=2]
+ %exitcond = icmp eq i32 %indvar.next, 256 ; <i1> [#uses=1]
+ br i1 %exitcond, label %bb4, label %bb2
+
+bb4: ; preds = %bb2
+ %indvar.next9 = add i32 %i.0.reg2mem.0.ph, 1 ; <i32> [#uses=2]
+ %exitcond10 = icmp eq i32 %indvar.next9, 32 ; <i1> [#uses=1]
+ br i1 %exitcond10, label %bb5, label %bb2
+
+bb5: ; preds = %bb4
+ %4 = load i32* getelementptr ([32 x [256 x i32]]* @table, i32 0, i32 9, i32 132), align 16 ; <i32> [#uses=1]
+ %5 = icmp eq i32 %4, -1116 ; <i1> [#uses=1]
+ br i1 %5, label %bb7, label %bb6
+
+bb6: ; preds = %bb5
+ tail call void @abort() noreturn nounwind
+ unreachable
+
+bb7: ; preds = %bb5
+ ret i32 0
+}
+
+declare void @abort() noreturn nounwind
diff --git a/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll b/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll
new file mode 100644
index 0000000000..4032a599e8
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll
@@ -0,0 +1,130 @@
+; RUN: llc < %s -mtriple=i386-apple-darwin11
+
+define void @_ZN4llvm20SelectionDAGLowering14visitInlineAsmENS_8CallSiteE() nounwind ssp align 2 {
+entry:
+ br i1 undef, label %bb3.i, label %bb4.i
+
+bb3.i: ; preds = %entry
+ unreachable
+
+bb4.i: ; preds = %entry
+ br i1 undef, label %bb.i.i, label %_ZNK4llvm8CallSite14getCalledValueEv.exit
+
+bb.i.i: ; preds = %bb4.i
+ unreachable
+
+_ZNK4llvm8CallSite14getCalledValueEv.exit: ; preds = %bb4.i
+ br i1 undef, label %_ZN4llvm4castINS_9InlineAsmEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit, label %bb6.i
+
+bb6.i: ; preds = %_ZNK4llvm8CallSite14getCalledValueEv.exit
+ unreachable
+
+_ZN4llvm4castINS_9InlineAsmEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit: ; preds = %_ZNK4llvm8CallSite14getCalledValueEv.exit
+ br i1 undef, label %_ZL25hasInlineAsmMemConstraintRSt6vectorIN4llvm9InlineAsm14ConstraintInfoESaIS2_EERKNS0_14TargetLoweringE.exit, label %bb.i
+
+bb.i: ; preds = %_ZN4llvm4castINS_9InlineAsmEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit
+ br label %_ZL25hasInlineAsmMemConstraintRSt6vectorIN4llvm9InlineAsm14ConstraintInfoESaIS2_EERKNS0_14TargetLoweringE.exit
+
+_ZL25hasInlineAsmMemConstraintRSt6vectorIN4llvm9InlineAsm14ConstraintInfoESaIS2_EERKNS0_14TargetLoweringE.exit: ; preds = %bb.i, %_ZN4llvm4castINS_9InlineAsmEPNS_5ValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS6_.exit
+ br i1 undef, label %bb50, label %bb27
+
+bb27: ; preds = %_ZL25hasInlineAsmMemConstraintRSt6vectorIN4llvm9InlineAsm14ConstraintInfoESaIS2_EERKNS0_14TargetLoweringE.exit
+ br i1 undef, label %bb1.i727, label %bb.i.i726
+
+bb.i.i726: ; preds = %bb27
+ unreachable
+
+bb1.i727: ; preds = %bb27
+ unreachable
+
+bb50: ; preds = %_ZL25hasInlineAsmMemConstraintRSt6vectorIN4llvm9InlineAsm14ConstraintInfoESaIS2_EERKNS0_14TargetLoweringE.exit
+ br label %bb107
+
+bb51: ; preds = %bb107
+ br i1 undef, label %bb105, label %bb106
+
+bb105: ; preds = %bb51
+ unreachable
+
+bb106: ; preds = %bb51
+ br label %bb107
+
+bb107: ; preds = %bb106, %bb50
+ br i1 undef, label %bb108, label %bb51
+
+bb108: ; preds = %bb107
+ br i1 undef, label %bb242, label %bb114
+
+bb114: ; preds = %bb108
+ br i1 undef, label %bb141, label %bb116
+
+bb116: ; preds = %bb114
+ br i1 undef, label %bb120, label %bb121
+
+bb120: ; preds = %bb116
+ unreachable
+
+bb121: ; preds = %bb116
+ unreachable
+
+bb141: ; preds = %bb114
+ br i1 undef, label %bb182, label %bb143
+
+bb143: ; preds = %bb141
+ br label %bb157
+
+bb144: ; preds = %bb.i.i.i843
+ switch i32 undef, label %bb155 [
+ i32 2, label %bb153
+ i32 6, label %bb153
+ i32 4, label %bb153
+ ]
+
+bb153: ; preds = %bb144, %bb144, %bb144
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ br label %bb157
+
+bb155: ; preds = %bb144
+ unreachable
+
+bb157: ; preds = %bb153, %bb143
+ %indvar = phi i32 [ %indvar.next, %bb153 ], [ 0, %bb143 ] ; <i32> [#uses=2]
+ %0 = icmp eq i32 undef, %indvar ; <i1> [#uses=1]
+ switch i16 undef, label %bb6.i841 [
+ i16 9, label %_ZN4llvm4castINS_14ConstantSDNodeENS_7SDValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS5_.exit
+ i16 26, label %_ZN4llvm4castINS_14ConstantSDNodeENS_7SDValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS5_.exit
+ ]
+
+bb6.i841: ; preds = %bb157
+ unreachable
+
+_ZN4llvm4castINS_14ConstantSDNodeENS_7SDValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS5_.exit: ; preds = %bb157, %bb157
+ br i1 undef, label %bb.i.i.i843, label %bb1.i.i.i844
+
+bb.i.i.i843: ; preds = %_ZN4llvm4castINS_14ConstantSDNodeENS_7SDValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS5_.exit
+ br i1 %0, label %bb158, label %bb144
+
+bb1.i.i.i844: ; preds = %_ZN4llvm4castINS_14ConstantSDNodeENS_7SDValueEEENS_10cast_rettyIT_T0_E8ret_typeERKS5_.exit
+ unreachable
+
+bb158: ; preds = %bb.i.i.i843
+ br i1 undef, label %bb177, label %bb176
+
+bb176: ; preds = %bb158
+ unreachable
+
+bb177: ; preds = %bb158
+ br i1 undef, label %bb179, label %bb178
+
+bb178: ; preds = %bb177
+ unreachable
+
+bb179: ; preds = %bb177
+ unreachable
+
+bb182: ; preds = %bb141
+ unreachable
+
+bb242: ; preds = %bb108
+ unreachable
+}
diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll
new file mode 100644
index 0000000000..36941ad6d3
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll
@@ -0,0 +1,24 @@
+; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmpl \$4}
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin9"
+
+; This is like change-compare-stride-trickiness-1.ll except the comparison
+; happens before the relevant use, so the comparison stride can't be
+; easily changed.
+
+define void @foo() nounwind {
+entry:
+ br label %loop
+
+loop:
+ %indvar = phi i32 [ 0, %entry ], [ %i.2.0.us1534, %loop ] ; <i32> [#uses=1]
+ %i.2.0.us1534 = add i32 %indvar, 1 ; <i32> [#uses=3]
+ %tmp611.us1535 = icmp eq i32 %i.2.0.us1534, 4 ; <i1> [#uses=2]
+ %tmp623.us1538 = select i1 %tmp611.us1535, i32 6, i32 0 ; <i32> [#uses=0]
+ %tmp628.us1540 = shl i32 %i.2.0.us1534, 1 ; <i32> [#uses=1]
+ %tmp645646647.us1547 = sext i32 %tmp628.us1540 to i64 ; <i64> [#uses=0]
+ br i1 %tmp611.us1535, label %exit, label %loop
+
+exit:
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll
new file mode 100644
index 0000000000..ea8a259ecd
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll
@@ -0,0 +1,26 @@
+; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmp. \$8}
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin9"
+
+; The comparison happens after the relevant use, so the stride can easily
+; be changed. The comparison can be done in a narrower mode than the
+; induction variable.
+
+define void @foo() nounwind {
+entry:
+ br label %loop
+
+loop:
+ %indvar = phi i32 [ 0, %entry ], [ %i.2.0.us1534, %loop ] ; <i32> [#uses=1]
+ %i.2.0.us1534 = add i32 %indvar, 1 ; <i32> [#uses=3]
+ %tmp628.us1540 = shl i32 %i.2.0.us1534, 1 ; <i32> [#uses=1]
+ %tmp645646647.us1547 = sext i32 %tmp628.us1540 to i64 ; <i64> [#uses=1]
+ store i64 %tmp645646647.us1547, i64* null
+ %tmp611.us1535 = icmp eq i32 %i.2.0.us1534, 4 ; <i1> [#uses=2]
+ %tmp623.us1538 = select i1 %tmp611.us1535, i32 6, i32 0 ; <i32> [#uses=1]
+ store i32 %tmp623.us1538, i32* null
+ br i1 %tmp611.us1535, label %exit, label %loop
+
+exit:
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-2.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-2.ll
new file mode 100644
index 0000000000..ae27383895
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-2.ll
@@ -0,0 +1,58 @@
+; RUN: llc < %s
+; PR4222
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "x86_64-pc-linux-gnu"
+module asm ".ident\09\22$FreeBSD: head/sys/amd64/amd64/minidump_machdep.c 184499 2008-10-31 10:11:35Z kib $\22"
+ %struct.dumperinfo = type <{ i32 (i8*, i8*, i64, i64, i64)*, i8*, i32, i32, i64, i64 }>
+
+define void @minidumpsys(%struct.dumperinfo* %di) nounwind {
+entry:
+ br label %if.end
+
+if.end: ; preds = %if.end52, %entry
+ br label %for.cond.i.preheader
+
+for.cond.i.preheader: ; preds = %if.end52, %if.end
+ %indvar688 = phi i64 [ 0, %if.end ], [ %indvar.next689, %if.end52 ] ; <i64> [#uses=3]
+ %tmp690 = shl i64 %indvar688, 12 ; <i64> [#uses=1]
+ %pa.0642 = add i64 %tmp690, 0 ; <i64> [#uses=1]
+ %indvar688703 = trunc i64 %indvar688 to i32 ; <i32> [#uses=1]
+ %tmp692693 = add i32 %indvar688703, 1 ; <i32> [#uses=1]
+ %phitmp = sext i32 %tmp692693 to i64 ; <i64> [#uses=1]
+ br i1 false, label %if.end52, label %land.lhs.true.i
+
+land.lhs.true.i: ; preds = %for.cond.i.preheader
+ %shr2.i = lshr i64 %pa.0642, 18 ; <i64> [#uses=0]
+ unreachable
+
+if.end52: ; preds = %for.cond.i.preheader
+ %phitmp654 = icmp ult i64 %phitmp, 512 ; <i1> [#uses=1]
+ %indvar.next689 = add i64 %indvar688, 1 ; <i64> [#uses=1]
+ br i1 %phitmp654, label %for.cond.i.preheader, label %if.end
+}
+
+define void @promote(%struct.dumperinfo* %di) nounwind {
+entry:
+ br label %if.end
+
+if.end: ; preds = %if.end52, %entry
+ br label %for.cond.i.preheader
+
+for.cond.i.preheader: ; preds = %if.end52, %if.end
+ %indvar688 = phi i32 [ 0, %if.end ], [ %indvar.next689, %if.end52 ] ; <i64> [#uses=3]
+ %tmp690 = shl i32 %indvar688, 12 ; <i64> [#uses=1]
+ %pa.0642 = add i32 %tmp690, 0 ; <i64> [#uses=1]
+ %tmp692693 = add i32 %indvar688, 1 ; <i32> [#uses=1]
+ %phitmp = sext i32 %tmp692693 to i64 ; <i64> [#uses=1]
+ br i1 false, label %if.end52, label %land.lhs.true.i
+
+land.lhs.true.i: ; preds = %for.cond.i.preheader
+ %shr2.i = lshr i32 %pa.0642, 18 ; <i64> [#uses=0]
+ unreachable
+
+if.end52: ; preds = %for.cond.i.preheader
+ %phitmp654 = icmp ult i64 %phitmp, 512 ; <i1> [#uses=1]
+ %indvar.next689 = add i32 %indvar688, 1 ; <i64> [#uses=1]
+ br i1 %phitmp654, label %for.cond.i.preheader, label %if.end
+}
diff --git a/test/Transforms/LoopStrengthReduce/count-to-zero.ll b/test/Transforms/LoopStrengthReduce/count-to-zero.ll
new file mode 100644
index 0000000000..8cc3b5c103
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/count-to-zero.ll
@@ -0,0 +1,42 @@
+; RUN: opt < %s -loop-reduce -S | FileCheck %s
+; rdar://7382068
+
+define void @t(i32 %c) nounwind optsize {
+entry:
+ br label %bb6
+
+bb1: ; preds = %bb6
+ %tmp = icmp eq i32 %c_addr.1, 20 ; <i1> [#uses=1]
+ br i1 %tmp, label %bb2, label %bb3
+
+bb2: ; preds = %bb1
+ %tmp1 = tail call i32 @f20(i32 %c_addr.1) nounwind ; <i32> [#uses=1]
+ br label %bb7
+
+bb3: ; preds = %bb1
+ %tmp2 = icmp slt i32 %c_addr.1, 10 ; <i1> [#uses=1]
+ %tmp3 = add nsw i32 %c_addr.1, 1 ; <i32> [#uses=1]
+ %tmp4 = add i32 %c_addr.1, -1 ; <i32> [#uses=1]
+ %c_addr.1.be = select i1 %tmp2, i32 %tmp3, i32 %tmp4 ; <i32> [#uses=1]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+; CHECK: sub i32 %lsr.iv, 1
+ br label %bb6
+
+bb6: ; preds = %bb3, %entry
+ %indvar = phi i32 [ %indvar.next, %bb3 ], [ 0, %entry ] ; <i32> [#uses=2]
+ %c_addr.1 = phi i32 [ %c_addr.1.be, %bb3 ], [ %c, %entry ] ; <i32> [#uses=7]
+ %tmp5 = icmp eq i32 %indvar, 9999 ; <i1> [#uses=1]
+; CHECK: icmp eq i32 %lsr.iv, 0
+ %tmp6 = icmp eq i32 %c_addr.1, 100 ; <i1> [#uses=1]
+ %or.cond = or i1 %tmp5, %tmp6 ; <i1> [#uses=1]
+ br i1 %or.cond, label %bb7, label %bb1
+
+bb7: ; preds = %bb6, %bb2
+ %c_addr.0 = phi i32 [ %tmp1, %bb2 ], [ %c_addr.1, %bb6 ] ; <i32> [#uses=1]
+ tail call void @bar(i32 %c_addr.0) nounwind
+ ret void
+}
+
+declare i32 @f20(i32)
+
+declare void @bar(i32)
diff --git a/test/Transforms/LoopStrengthReduce/dead-phi.ll b/test/Transforms/LoopStrengthReduce/dead-phi.ll
new file mode 100644
index 0000000000..07a942f70b
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dead-phi.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -loop-reduce -S | grep phi | count 1
+
+define void @foo(i32 %n) {
+entry:
+ br label %loop
+
+loop:
+ %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
+
+ ; These three instructions form an isolated cycle and can be deleted.
+ %j = phi i32 [ 0, %entry ], [ %j.y, %loop ]
+ %j.x = add i32 %j, 1
+ %j.y = mul i32 %j.x, 2
+
+ %i.next = add i32 %i, 1
+ %c = icmp ne i32 %i.next, %n
+ br i1 %c, label %loop, label %exit
+
+exit:
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/dg.exp b/test/Transforms/LoopStrengthReduce/dg.exp
new file mode 100644
index 0000000000..f2005891a5
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dg.exp
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
diff --git a/test/Transforms/LoopStrengthReduce/different-type-ivs.ll b/test/Transforms/LoopStrengthReduce/different-type-ivs.ll
new file mode 100644
index 0000000000..8cdd264591
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/different-type-ivs.ll
@@ -0,0 +1,25 @@
+; RUN: opt < %s -loop-reduce -disable-output
+; Test to make sure that loop-reduce never crashes on IV's
+; with different types but identical strides.
+
+define void @foo() {
+entry:
+ br label %no_exit
+no_exit: ; preds = %no_exit, %entry
+ %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %no_exit ] ; <i32> [#uses=3]
+ %indvar.upgrd.1 = trunc i32 %indvar to i16 ; <i16> [#uses=1]
+ %X.0.0 = mul i16 %indvar.upgrd.1, 1234 ; <i16> [#uses=1]
+ %tmp. = mul i32 %indvar, 1234 ; <i32> [#uses=1]
+ %tmp.5 = sext i16 %X.0.0 to i32 ; <i32> [#uses=1]
+ %tmp.3 = call i32 (...)* @bar( i32 %tmp.5, i32 %tmp. ) ; <i32> [#uses=0]
+ %tmp.0 = call i1 @pred( ) ; <i1> [#uses=1]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ br i1 %tmp.0, label %return, label %no_exit
+return: ; preds = %no_exit
+ ret void
+}
+
+declare i1 @pred()
+
+declare i32 @bar(...)
+
diff --git a/test/Transforms/LoopStrengthReduce/dont-hoist-simple-loop-constants.ll b/test/Transforms/LoopStrengthReduce/dont-hoist-simple-loop-constants.ll
new file mode 100644
index 0000000000..4136486fef
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dont-hoist-simple-loop-constants.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: not grep {bitcast i32 1 to i32}
+; END.
+; The setlt wants to use a value that is incremented one more than the dominant
+; IV. Don't insert the 1 outside the loop, preventing folding it into the add.
+
+define void @test([700 x i32]* %nbeaux_.0__558, i32* %i_.16574) {
+then.0:
+ br label %no_exit.2
+no_exit.2: ; preds = %no_exit.2, %then.0
+ %indvar630 = phi i32 [ 0, %then.0 ], [ %indvar.next631, %no_exit.2 ] ; <i32> [#uses=4]
+ %gep.upgrd.1 = zext i32 %indvar630 to i64 ; <i64> [#uses=1]
+ %tmp.38 = getelementptr [700 x i32]* %nbeaux_.0__558, i32 0, i64 %gep.upgrd.1 ; <i32*> [#uses=1]
+ store i32 0, i32* %tmp.38
+ %inc.2 = add i32 %indvar630, 2 ; <i32> [#uses=2]
+ %tmp.34 = icmp slt i32 %inc.2, 701 ; <i1> [#uses=1]
+ %indvar.next631 = add i32 %indvar630, 1 ; <i32> [#uses=1]
+ br i1 %tmp.34, label %no_exit.2, label %loopexit.2.loopexit
+loopexit.2.loopexit: ; preds = %no_exit.2
+ store i32 %inc.2, i32* %i_.16574
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/dont_insert_redundant_ops.ll b/test/Transforms/LoopStrengthReduce/dont_insert_redundant_ops.ll
new file mode 100644
index 0000000000..90051e3542
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dont_insert_redundant_ops.ll
@@ -0,0 +1,36 @@
+; Check that this test makes INDVAR and related stuff dead.
+; RUN: opt < %s -loop-reduce -S | grep phi | count 2
+
+declare i1 @pred()
+
+define void @test1({ i32, i32 }* %P) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=3]
+ %gep1 = getelementptr { i32, i32 }* %P, i32 %INDVAR, i32 0 ; <i32*> [#uses=1]
+ store i32 0, i32* %gep1
+ %gep2 = getelementptr { i32, i32 }* %P, i32 %INDVAR, i32 1 ; <i32*> [#uses=1]
+ store i32 0, i32* %gep2
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
+define void @test2([2 x i32]* %P) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=3]
+ %gep1 = getelementptr [2 x i32]* %P, i32 %INDVAR, i64 0 ; <i32*> [#uses=1]
+ store i32 0, i32* %gep1
+ %gep2 = getelementptr [2 x i32]* %P, i32 %INDVAR, i64 1 ; <i32*> [#uses=1]
+ store i32 0, i32* %gep2
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/dont_reduce_bytes.ll b/test/Transforms/LoopStrengthReduce/dont_reduce_bytes.ll
new file mode 100644
index 0000000000..20300002eb
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dont_reduce_bytes.ll
@@ -0,0 +1,22 @@
+; Don't reduce the byte access to P[i], at least not on targets that
+; support an efficient 'mem[r1+r2]' addressing mode.
+
+; RUN: opt < %s -loop-reduce -disable-output
+
+
+declare i1 @pred(i32)
+
+define void @test(i8* %PTR) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %STRRED = getelementptr i8* %PTR, i32 %INDVAR ; <i8*> [#uses=1]
+ store i8 0, i8* %STRRED
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=2]
+ ;; cannot eliminate indvar
+ %cond = call i1 @pred( i32 %INDVAR2 ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/dont_reverse.ll b/test/Transforms/LoopStrengthReduce/dont_reverse.ll
new file mode 100644
index 0000000000..4c5db04b21
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/dont_reverse.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -loop-reduce -S \
+; RUN: | grep {icmp eq i2 %lsr.iv.next, %xmp4344}
+
+; Don't reverse the iteration if the rhs of the compare is defined
+; inside the loop.
+
+define void @Fill_Buffer(i2* %p) nounwind {
+entry:
+ br label %bb8
+
+bb8:
+ %indvar34 = phi i32 [ 0, %entry ], [ %indvar.next35, %bb8 ]
+ %indvar3451 = trunc i32 %indvar34 to i2
+ %xmp4344 = load i2* %p
+ %xmp104 = icmp eq i2 %indvar3451, %xmp4344
+ %indvar.next35 = add i32 %indvar34, 1
+ br i1 %xmp104, label %bb10, label %bb8
+
+bb10:
+ unreachable
+}
diff --git a/test/Transforms/LoopStrengthReduce/exit_compare_live_range.ll b/test/Transforms/LoopStrengthReduce/exit_compare_live_range.ll
new file mode 100644
index 0000000000..abbfda6e92
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/exit_compare_live_range.ll
@@ -0,0 +1,21 @@
+; Make sure that the compare instruction occurs after the increment to avoid
+; having overlapping live ranges that result in copies. We want the setcc
+; instruction immediately before the conditional branch.
+;
+; RUN: opt -S -loop-reduce %s | FileCheck %s
+
+define void @foo(float* %D, i32 %E) {
+entry:
+ br label %no_exit
+no_exit: ; preds = %no_exit, %entry
+ %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %no_exit ] ; <i32> [#uses=1]
+ volatile store float 0.000000e+00, float* %D
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=2]
+; CHECK: icmp
+; CHECK-NEXT: br i1
+ %exitcond = icmp eq i32 %indvar.next, %E ; <i1> [#uses=1]
+ br i1 %exitcond, label %loopexit, label %no_exit
+loopexit: ; preds = %no_exit
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll
new file mode 100644
index 0000000000..f86638b0a8
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll
@@ -0,0 +1,23 @@
+; Check that the index of 'P[outer]' is pulled out of the loop.
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: not grep {getelementptr.*%outer.*%INDVAR}
+
+declare i1 @pred()
+
+declare i32 @foo()
+
+define void @test([10000 x i32]* %P) {
+; <label>:0
+ %outer = call i32 @foo( ) ; <i32> [#uses=1]
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %STRRED = getelementptr [10000 x i32]* %P, i32 %outer, i32 %INDVAR ; <i32*> [#uses=1]
+ store i32 0, i32* %STRRED
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll
new file mode 100644
index 0000000000..37acf0f61d
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll
@@ -0,0 +1,20 @@
+; Check that the index of 'P[outer]' is pulled out of the loop.
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: not grep {getelementptr.*%outer.*%INDVAR}
+
+declare i1 @pred()
+
+define void @test([10000 x i32]* %P, i32 %outer) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %STRRED = getelementptr [10000 x i32]* %P, i32 %outer, i32 %INDVAR ; <i32*> [#uses=1]
+ store i32 0, i32* %STRRED
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/nested-reduce.ll b/test/Transforms/LoopStrengthReduce/nested-reduce.ll
new file mode 100644
index 0000000000..58b8d3eecd
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/nested-reduce.ll
@@ -0,0 +1,49 @@
+; RUN: opt < %s -loop-reduce -S | not grep mul
+
+; Make sure we don't get a multiply by 6 in this loop.
+
+define i32 @foo(i32 %A, i32 %B, i32 %C, i32 %D) {
+entry:
+ %tmp.5 = icmp sgt i32 %C, 0 ; <i1> [#uses=1]
+ %tmp.25 = and i32 %A, 1 ; <i32> [#uses=1]
+ br label %loopentry.1
+loopentry.1: ; preds = %loopexit.1, %entry
+ %indvar20 = phi i32 [ 0, %entry ], [ %indvar.next21, %loopexit.1 ] ; <i32> [#uses=2]
+ %k.1 = phi i32 [ 0, %entry ], [ %k.1.3, %loopexit.1 ] ; <i32> [#uses=2]
+ br i1 %tmp.5, label %no_exit.1.preheader, label %loopexit.1
+no_exit.1.preheader: ; preds = %loopentry.1
+ %i.0.0 = bitcast i32 %indvar20 to i32 ; <i32> [#uses=1]
+ %tmp.9 = mul i32 %i.0.0, 6 ; <i32> [#uses=1]
+ br label %no_exit.1.outer
+no_exit.1.outer: ; preds = %cond_true, %no_exit.1.preheader
+ %k.1.2.ph = phi i32 [ %k.1, %no_exit.1.preheader ], [ %k.09, %cond_true ] ; <i32> [#uses=2]
+ %j.1.2.ph = phi i32 [ 0, %no_exit.1.preheader ], [ %inc.1, %cond_true ] ; <i32> [#uses=1]
+ br label %no_exit.1
+no_exit.1: ; preds = %cond_continue, %no_exit.1.outer
+ %indvar.ui = phi i32 [ 0, %no_exit.1.outer ], [ %indvar.next, %cond_continue ] ; <i32> [#uses=2]
+ %indvar = bitcast i32 %indvar.ui to i32 ; <i32> [#uses=1]
+ %j.1.2 = add i32 %indvar, %j.1.2.ph ; <i32> [#uses=2]
+ %tmp.11 = add i32 %j.1.2, %tmp.9 ; <i32> [#uses=1]
+ %tmp.12 = trunc i32 %tmp.11 to i8 ; <i8> [#uses=1]
+ %shift.upgrd.1 = zext i8 %tmp.12 to i32 ; <i32> [#uses=1]
+ %tmp.13 = shl i32 %D, %shift.upgrd.1 ; <i32> [#uses=2]
+ %tmp.15 = icmp eq i32 %tmp.13, %B ; <i1> [#uses=1]
+ %inc.1 = add i32 %j.1.2, 1 ; <i32> [#uses=3]
+ br i1 %tmp.15, label %cond_true, label %cond_continue
+cond_true: ; preds = %no_exit.1
+ %tmp.26 = and i32 %tmp.25, %tmp.13 ; <i32> [#uses=1]
+ %k.09 = add i32 %tmp.26, %k.1.2.ph ; <i32> [#uses=2]
+ %tmp.517 = icmp slt i32 %inc.1, %C ; <i1> [#uses=1]
+ br i1 %tmp.517, label %no_exit.1.outer, label %loopexit.1
+cond_continue: ; preds = %no_exit.1
+ %tmp.519 = icmp slt i32 %inc.1, %C ; <i1> [#uses=1]
+ %indvar.next = add i32 %indvar.ui, 1 ; <i32> [#uses=1]
+ br i1 %tmp.519, label %no_exit.1, label %loopexit.1
+loopexit.1: ; preds = %cond_continue, %cond_true, %loopentry.1
+ %k.1.3 = phi i32 [ %k.1, %loopentry.1 ], [ %k.09, %cond_true ], [ %k.1.2.ph, %cond_continue ] ; <i32> [#uses=2]
+ %indvar.next21 = add i32 %indvar20, 1 ; <i32> [#uses=2]
+ %exitcond = icmp eq i32 %indvar.next21, 4 ; <i1> [#uses=1]
+ br i1 %exitcond, label %loopexit.0, label %loopentry.1
+loopexit.0: ; preds = %loopexit.1
+ ret i32 %k.1.3
+}
diff --git a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll
new file mode 100644
index 0000000000..a032cc9735
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll
@@ -0,0 +1,24 @@
+; Check that this test makes INDVAR and related stuff dead, because P[indvar]
+; gets reduced, making INDVAR dead.
+
+; RUN: opt < %s -loop-reduce -S | not grep INDVAR
+
+declare i1 @pred()
+
+declare i32 @getidx()
+
+define void @test([10000 x i32]* %P) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %idx = call i32 @getidx( ) ; <i32> [#uses=1]
+ %STRRED = getelementptr [10000 x i32]* %P, i32 %INDVAR, i32 %idx ; <i32*> [#uses=1]
+ store i32 0, i32* %STRRED
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/phi_node_update_multiple_preds.ll b/test/Transforms/LoopStrengthReduce/phi_node_update_multiple_preds.ll
new file mode 100644
index 0000000000..7ef494debd
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/phi_node_update_multiple_preds.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -loop-reduce -disable-output
+; LSR should not crash on this.
+
+define fastcc void @loadloop() {
+entry:
+ switch i8 0, label %shortcirc_next [
+ i8 32, label %loopexit.2
+ i8 59, label %loopexit.2
+ ]
+shortcirc_next: ; preds = %no_exit.2, %entry
+ %indvar37 = phi i32 [ 0, %entry ], [ %indvar.next38, %no_exit.2 ] ; <i32> [#uses=3]
+ %gep.upgrd.1 = zext i32 %indvar37 to i64 ; <i64> [#uses=1]
+ %wp.2.4 = getelementptr i8* null, i64 %gep.upgrd.1 ; <i8*> [#uses=1]
+ br i1 false, label %loopexit.2, label %no_exit.2
+no_exit.2: ; preds = %shortcirc_next
+ %wp.2.4.rec = bitcast i32 %indvar37 to i32 ; <i32> [#uses=1]
+ %inc.1.rec = add i32 %wp.2.4.rec, 1 ; <i32> [#uses=1]
+ %inc.1 = getelementptr i8* null, i32 %inc.1.rec ; <i8*> [#uses=2]
+ %indvar.next38 = add i32 %indvar37, 1 ; <i32> [#uses=1]
+ switch i8 0, label %shortcirc_next [
+ i8 32, label %loopexit.2
+ i8 59, label %loopexit.2
+ ]
+loopexit.2: ; preds = %no_exit.2, %no_exit.2, %shortcirc_next, %entry, %entry
+ %wp.2.7 = phi i8* [ null, %entry ], [ null, %entry ], [ %wp.2.4, %shortcirc_next ], [ %inc.1, %no_exit.2 ], [ %inc.1, %no_exit.2 ] ; <i8*> [#uses=0]
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/pr2537.ll b/test/Transforms/LoopStrengthReduce/pr2537.ll
new file mode 100644
index 0000000000..73c3152d30
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/pr2537.ll
@@ -0,0 +1,21 @@
+; RUN: opt < %s -loop-reduce -disable-output
+; PR 2537
+
+define void @a() {
+entry:
+ br label %dobody
+
+dobody: ; preds = %dobody, %entry
+ %y.0 = phi i128 [ 0, %entry ], [ %add, %dobody ]
+ %x.0 = phi i128 [ 0, %entry ], [ %add2, %dobody ]
+ %add = add i128 %y.0, shl (i128 1, i128 64)
+ %add2 = add i128 %x.0, shl (i128 1, i128 48)
+ call void @b( i128 %add )
+ %cmp = icmp ult i128 %add2, shl (i128 1, i128 64)
+ br i1 %cmp, label %dobody, label %afterdo
+
+afterdo: ; preds = %dobody
+ ret void
+}
+
+declare void @b(i128 %add) \ No newline at end of file
diff --git a/test/Transforms/LoopStrengthReduce/pr2570.ll b/test/Transforms/LoopStrengthReduce/pr2570.ll
new file mode 100644
index 0000000000..aafd24ebba
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/pr2570.ll
@@ -0,0 +1,287 @@
+; RUN: opt < %s -loop-reduce -S | grep {phi\\>} | count 10
+; PR2570
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
+target triple = "i386-pc-linux-gnu"
+@g_14 = internal global i32 1 ; <i32*> [#uses=1]
+@g_39 = internal global i16 -5 ; <i16*> [#uses=2]
+@g_43 = internal global i32 -6 ; <i32*> [#uses=3]
+@g_33 = internal global i32 -1269044541 ; <i32*> [#uses=1]
+@g_137 = internal global i32 8 ; <i32*> [#uses=1]
+@g_82 = internal global i32 -5 ; <i32*> [#uses=3]
+@g_91 = internal global i32 1 ; <i32*> [#uses=1]
+@g_197 = internal global i32 1 ; <i32*> [#uses=4]
+@g_207 = internal global i32 1 ; <i32*> [#uses=2]
+@g_222 = internal global i16 4165 ; <i16*> [#uses=1]
+@g_247 = internal global i8 -21 ; <i8*> [#uses=2]
+@g_260 = internal global i32 1 ; <i32*> [#uses=2]
+@g_221 = internal global i16 -17503 ; <i16*> [#uses=3]
+@g_267 = internal global i16 1 ; <i16*> [#uses=1]
+@llvm.used = appending global [1 x i8*] [ i8* bitcast (i32 (i32, i32, i16, i32, i8, i32)* @func_44 to i8*) ], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0]
+
+define i32 @func_44(i32 %p_45, i32 %p_46, i16 zeroext %p_48, i32 %p_49, i8 zeroext %p_50, i32 %p_52) nounwind {
+entry:
+ tail call i32 @func_116( i8 zeroext 2 ) nounwind ; <i32>:0 [#uses=0]
+ tail call i32 @func_63( i16 signext 2 ) nounwind ; <i32>:1 [#uses=1]
+ load i16* @g_39, align 2 ; <i16>:2 [#uses=1]
+ tail call i32 @func_63( i16 signext %2 ) nounwind ; <i32>:3 [#uses=1]
+ trunc i32 %3 to i16 ; <i16>:4 [#uses=1]
+ and i16 %4, 1 ; <i16>:5 [#uses=1]
+ trunc i32 %p_52 to i8 ; <i8>:6 [#uses=1]
+ trunc i32 %1 to i16 ; <i16>:7 [#uses=1]
+ tail call i32 @func_74( i16 zeroext %5, i8 zeroext %6, i16 zeroext %7, i16 zeroext 0 ) nounwind ; <i32>:8 [#uses=0]
+ tail call i32 @func_124( i32 544824386 ) nounwind ; <i32>:9 [#uses=0]
+ zext i8 %p_50 to i32 ; <i32>:10 [#uses=1]
+ load i32* @g_43, align 4 ; <i32>:11 [#uses=1]
+ icmp sle i32 %10, %11 ; <i1>:12 [#uses=1]
+ zext i1 %12 to i32 ; <i32>:13 [#uses=2]
+ load i8* @g_247, align 1 ; <i8>:14 [#uses=1]
+ trunc i32 %p_45 to i16 ; <i16>:15 [#uses=1]
+ zext i8 %14 to i16 ; <i16>:16 [#uses=1]
+ tail call i32 @func_74( i16 zeroext %15, i8 zeroext 0, i16 zeroext %16, i16 zeroext 23618 ) nounwind ; <i32>:17 [#uses=4]
+ icmp slt i32 %17, 0 ; <i1>:18 [#uses=1]
+ br i1 %18, label %bb162, label %bb152
+
+bb152: ; preds = %entry
+ lshr i32 2147483647, %13 ; <i32>:19 [#uses=1]
+ icmp slt i32 %19, %17 ; <i1>:20 [#uses=1]
+ select i1 %20, i32 0, i32 %13 ; <i32>:21 [#uses=1]
+ %.348 = shl i32 %17, %21 ; <i32> [#uses=1]
+ br label %bb162
+
+bb162: ; preds = %bb152, %entry
+ %.0346 = phi i32 [ %.348, %bb152 ], [ %17, %entry ] ; <i32> [#uses=1]
+ tail call i32 @func_124( i32 1 ) nounwind ; <i32>:22 [#uses=1]
+ mul i32 %22, %.0346 ; <i32>:23 [#uses=1]
+ icmp slt i32 %p_45, 0 ; <i1>:24 [#uses=1]
+ icmp ugt i32 %p_45, 31 ; <i1>:25 [#uses=1]
+ %or.cond = or i1 %24, %25 ; <i1> [#uses=1]
+ br i1 %or.cond, label %bb172, label %bb168
+
+bb168: ; preds = %bb162
+ lshr i32 2147483647, %p_45 ; <i32>:26 [#uses=1]
+ shl i32 1392859848, %p_45 ; <i32>:27 [#uses=1]
+ icmp slt i32 %26, 1392859848 ; <i1>:28 [#uses=1]
+ %.op355 = add i32 %27, 38978 ; <i32> [#uses=1]
+ %phitmp = select i1 %28, i32 1392898826, i32 %.op355 ; <i32> [#uses=1]
+ br label %bb172
+
+bb172: ; preds = %bb168, %bb162
+ %.0343 = phi i32 [ %phitmp, %bb168 ], [ 1392898826, %bb162 ] ; <i32> [#uses=2]
+ tail call i32 @func_84( i32 1, i16 zeroext 0, i16 zeroext 8 ) nounwind ; <i32>:29 [#uses=0]
+ icmp eq i32 %.0343, 0 ; <i1>:30 [#uses=1]
+ %.0341 = select i1 %30, i32 1, i32 %.0343 ; <i32> [#uses=1]
+ urem i32 %23, %.0341 ; <i32>:31 [#uses=1]
+ load i32* @g_137, align 4 ; <i32>:32 [#uses=4]
+ icmp slt i32 %32, 0 ; <i1>:33 [#uses=1]
+ br i1 %33, label %bb202, label %bb198
+
+bb198: ; preds = %bb172
+ %not. = icmp slt i32 %32, 1073741824 ; <i1> [#uses=1]
+ zext i1 %not. to i32 ; <i32>:34 [#uses=1]
+ %.351 = shl i32 %32, %34 ; <i32> [#uses=1]
+ br label %bb202
+
+bb202: ; preds = %bb198, %bb172
+ %.0335 = phi i32 [ %.351, %bb198 ], [ %32, %bb172 ] ; <i32> [#uses=1]
+ icmp ne i32 %31, %.0335 ; <i1>:35 [#uses=1]
+ zext i1 %35 to i32 ; <i32>:36 [#uses=1]
+ tail call i32 @func_128( i32 %36 ) nounwind ; <i32>:37 [#uses=0]
+ icmp eq i32 %p_45, 293685862 ; <i1>:38 [#uses=1]
+ br i1 %38, label %bb205, label %bb311
+
+bb205: ; preds = %bb202
+ icmp sgt i32 %p_46, 214 ; <i1>:39 [#uses=1]
+ zext i1 %39 to i32 ; <i32>:40 [#uses=2]
+ tail call i32 @func_128( i32 %40 ) nounwind ; <i32>:41 [#uses=0]
+ icmp sgt i32 %p_46, 65532 ; <i1>:42 [#uses=1]
+ zext i1 %42 to i16 ; <i16>:43 [#uses=1]
+ tail call i32 @func_74( i16 zeroext 23618, i8 zeroext -29, i16 zeroext %43, i16 zeroext 1 ) nounwind ; <i32>:44 [#uses=2]
+ tail call i32 @func_103( i16 zeroext -869 ) nounwind ; <i32>:45 [#uses=0]
+ udiv i32 %44, 34162 ; <i32>:46 [#uses=1]
+ icmp ult i32 %44, 34162 ; <i1>:47 [#uses=1]
+ %.0331 = select i1 %47, i32 1, i32 %46 ; <i32> [#uses=1]
+ urem i32 293685862, %.0331 ; <i32>:48 [#uses=1]
+ tail call i32 @func_112( i32 %p_52, i16 zeroext 1 ) nounwind ; <i32>:49 [#uses=0]
+ icmp eq i32 %p_52, 0 ; <i1>:50 [#uses=2]
+ br i1 %50, label %bb222, label %bb215
+
+bb215: ; preds = %bb205
+ zext i16 %p_48 to i32 ; <i32>:51 [#uses=1]
+ icmp eq i16 %p_48, 0 ; <i1>:52 [#uses=1]
+ %.0329 = select i1 %52, i32 1, i32 %51 ; <i32> [#uses=1]
+ udiv i32 -1, %.0329 ; <i32>:53 [#uses=1]
+ icmp eq i32 %53, 0 ; <i1>:54 [#uses=1]
+ br i1 %54, label %bb222, label %bb223
+
+bb222: ; preds = %bb215, %bb205
+ br label %bb223
+
+bb223: ; preds = %bb222, %bb215
+ %iftmp.437.0 = phi i32 [ 0, %bb222 ], [ 1, %bb215 ] ; <i32> [#uses=1]
+ load i32* @g_91, align 4 ; <i32>:55 [#uses=3]
+ tail call i32 @func_103( i16 zeroext 4 ) nounwind ; <i32>:56 [#uses=0]
+ tail call i32 @func_112( i32 0, i16 zeroext -31374 ) nounwind ; <i32>:57 [#uses=0]
+ load i32* @g_197, align 4 ; <i32>:58 [#uses=1]
+ tail call i32 @func_124( i32 28156 ) nounwind ; <i32>:59 [#uses=1]
+ load i32* @g_260, align 4 ; <i32>:60 [#uses=1]
+ load i32* @g_43, align 4 ; <i32>:61 [#uses=1]
+ xor i32 %61, %60 ; <i32>:62 [#uses=1]
+ mul i32 %62, %59 ; <i32>:63 [#uses=1]
+ trunc i32 %63 to i8 ; <i8>:64 [#uses=1]
+ trunc i32 %58 to i16 ; <i16>:65 [#uses=1]
+ tail call i32 @func_74( i16 zeroext 0, i8 zeroext %64, i16 zeroext %65, i16 zeroext 0 ) nounwind ; <i32>:66 [#uses=2]
+ icmp slt i32 %66, 0 ; <i1>:67 [#uses=1]
+ icmp slt i32 %55, 0 ; <i1>:68 [#uses=1]
+ icmp ugt i32 %55, 31 ; <i1>:69 [#uses=1]
+ or i1 %68, %69 ; <i1>:70 [#uses=1]
+ %or.cond352 = or i1 %70, %67 ; <i1> [#uses=1]
+ select i1 %or.cond352, i32 0, i32 %55 ; <i32>:71 [#uses=1]
+ %.353 = ashr i32 %66, %71 ; <i32> [#uses=2]
+ load i16* @g_221, align 2 ; <i16>:72 [#uses=1]
+ zext i16 %72 to i32 ; <i32>:73 [#uses=1]
+ icmp ugt i32 %.353, 31 ; <i1>:74 [#uses=1]
+ select i1 %74, i32 0, i32 %.353 ; <i32>:75 [#uses=1]
+ %.0323 = lshr i32 %73, %75 ; <i32> [#uses=1]
+ add i32 %.0323, %iftmp.437.0 ; <i32>:76 [#uses=1]
+ and i32 %48, 255 ; <i32>:77 [#uses=2]
+ add i32 %77, 2042556439 ; <i32>:78 [#uses=1]
+ load i32* @g_207, align 4 ; <i32>:79 [#uses=2]
+ icmp ugt i32 %79, 31 ; <i1>:80 [#uses=1]
+ select i1 %80, i32 0, i32 %79 ; <i32>:81 [#uses=1]
+ %.0320 = lshr i32 %77, %81 ; <i32> [#uses=1]
+ icmp ne i32 %78, %.0320 ; <i1>:82 [#uses=1]
+ zext i1 %82 to i8 ; <i8>:83 [#uses=1]
+ tail call i32 @func_25( i8 zeroext %83 ) nounwind ; <i32>:84 [#uses=1]
+ xor i32 %84, 1 ; <i32>:85 [#uses=1]
+ load i32* @g_197, align 4 ; <i32>:86 [#uses=1]
+ add i32 %86, 1 ; <i32>:87 [#uses=1]
+ add i32 %87, %85 ; <i32>:88 [#uses=1]
+ icmp ugt i32 %76, %88 ; <i1>:89 [#uses=1]
+ br i1 %89, label %bb241, label %bb311
+
+bb241: ; preds = %bb223
+ store i16 -9, i16* @g_221, align 2
+ udiv i32 %p_52, 1538244727 ; <i32>:90 [#uses=1]
+ load i32* @g_207, align 4 ; <i32>:91 [#uses=1]
+ sub i32 %91, %90 ; <i32>:92 [#uses=1]
+ load i32* @g_14, align 4 ; <i32>:93 [#uses=1]
+ trunc i32 %93 to i16 ; <i16>:94 [#uses=1]
+ trunc i32 %p_46 to i16 ; <i16>:95 [#uses=2]
+ sub i16 %94, %95 ; <i16>:96 [#uses=1]
+ load i32* @g_197, align 4 ; <i32>:97 [#uses=1]
+ trunc i32 %97 to i16 ; <i16>:98 [#uses=1]
+ tail call i32 @func_55( i32 -346178830, i16 zeroext %98, i16 zeroext %95 ) nounwind ; <i32>:99 [#uses=0]
+ zext i16 %p_48 to i32 ; <i32>:100 [#uses=1]
+ load i8* @g_247, align 1 ; <i8>:101 [#uses=1]
+ zext i8 %101 to i32 ; <i32>:102 [#uses=1]
+ sub i32 %100, %102 ; <i32>:103 [#uses=1]
+ tail call i32 @func_55( i32 %103, i16 zeroext -2972, i16 zeroext %96 ) nounwind ; <i32>:104 [#uses=0]
+ xor i32 %92, 2968 ; <i32>:105 [#uses=1]
+ load i32* @g_197, align 4 ; <i32>:106 [#uses=1]
+ icmp ugt i32 %105, %106 ; <i1>:107 [#uses=1]
+ zext i1 %107 to i32 ; <i32>:108 [#uses=1]
+ store i32 %108, i32* @g_33, align 4
+ br label %bb248
+
+bb248: ; preds = %bb284, %bb241
+ %p_49_addr.1.reg2mem.0 = phi i32 [ 0, %bb241 ], [ %134, %bb284 ] ; <i32> [#uses=2]
+ %p_48_addr.2.reg2mem.0 = phi i16 [ %p_48, %bb241 ], [ %p_48_addr.1, %bb284 ] ; <i16> [#uses=1]
+ %p_46_addr.1.reg2mem.0 = phi i32 [ %p_46, %bb241 ], [ %133, %bb284 ] ; <i32> [#uses=1]
+ %p_45_addr.1.reg2mem.0 = phi i32 [ %p_45, %bb241 ], [ %p_45_addr.0, %bb284 ] ; <i32> [#uses=2]
+ tail call i32 @func_63( i16 signext 1 ) nounwind ; <i32>:109 [#uses=1]
+ icmp eq i32 %109, 0 ; <i1>:110 [#uses=1]
+ br i1 %110, label %bb272.thread, label %bb255.thread
+
+bb272.thread: ; preds = %bb248
+ store i32 1, i32* @g_82
+ load i16* @g_267, align 2 ; <i16>:111 [#uses=1]
+ icmp eq i16 %111, 0 ; <i1>:112 [#uses=1]
+ br i1 %112, label %bb311.loopexit.split, label %bb268
+
+bb255.thread: ; preds = %bb248
+ load i32* @g_260, align 4 ; <i32>:113 [#uses=1]
+ sub i32 %113, %p_52 ; <i32>:114 [#uses=1]
+ and i32 %114, -20753 ; <i32>:115 [#uses=1]
+ icmp ne i32 %115, 0 ; <i1>:116 [#uses=1]
+ zext i1 %116 to i16 ; <i16>:117 [#uses=1]
+ store i16 %117, i16* @g_221, align 2
+ br label %bb284
+
+bb268: ; preds = %bb268, %bb272.thread
+ %indvar = phi i32 [ 0, %bb272.thread ], [ %g_82.tmp.0, %bb268 ] ; <i32> [#uses=2]
+ %p_46_addr.0.reg2mem.0 = phi i32 [ %p_46_addr.1.reg2mem.0, %bb272.thread ], [ %119, %bb268 ] ; <i32> [#uses=1]
+ %g_82.tmp.0 = add i32 %indvar, 1 ; <i32> [#uses=2]
+ trunc i32 %p_46_addr.0.reg2mem.0 to i16 ; <i16>:118 [#uses=1]
+ and i32 %g_82.tmp.0, 28156 ; <i32>:119 [#uses=1]
+ add i32 %indvar, 2 ; <i32>:120 [#uses=4]
+ icmp sgt i32 %120, -1 ; <i1>:121 [#uses=1]
+ br i1 %121, label %bb268, label %bb274.split
+
+bb274.split: ; preds = %bb268
+ store i32 %120, i32* @g_82
+ br i1 %50, label %bb279, label %bb276
+
+bb276: ; preds = %bb274.split
+ store i16 0, i16* @g_222, align 2
+ br label %bb284
+
+bb279: ; preds = %bb274.split
+ icmp eq i32 %120, 0 ; <i1>:122 [#uses=1]
+ %.0317 = select i1 %122, i32 1, i32 %120 ; <i32> [#uses=1]
+ udiv i32 -8, %.0317 ; <i32>:123 [#uses=1]
+ trunc i32 %123 to i16 ; <i16>:124 [#uses=1]
+ br label %bb284
+
+bb284: ; preds = %bb279, %bb276, %bb255.thread
+ %p_49_addr.0 = phi i32 [ %p_49_addr.1.reg2mem.0, %bb279 ], [ %p_49_addr.1.reg2mem.0, %bb276 ], [ 0, %bb255.thread ] ; <i32> [#uses=1]
+ %p_48_addr.1 = phi i16 [ %124, %bb279 ], [ %118, %bb276 ], [ %p_48_addr.2.reg2mem.0, %bb255.thread ] ; <i16> [#uses=1]
+ %p_45_addr.0 = phi i32 [ %p_45_addr.1.reg2mem.0, %bb279 ], [ %p_45_addr.1.reg2mem.0, %bb276 ], [ 8, %bb255.thread ] ; <i32> [#uses=3]
+ load i32* @g_43, align 4 ; <i32>:125 [#uses=1]
+ trunc i32 %125 to i8 ; <i8>:126 [#uses=1]
+ tail call i32 @func_116( i8 zeroext %126 ) nounwind ; <i32>:127 [#uses=0]
+ lshr i32 65255, %p_45_addr.0 ; <i32>:128 [#uses=1]
+ icmp ugt i32 %p_45_addr.0, 31 ; <i1>:129 [#uses=1]
+ %.op = lshr i32 %128, 31 ; <i32> [#uses=1]
+ %.op.op = xor i32 %.op, 1 ; <i32> [#uses=1]
+ %.354..lobit.not = select i1 %129, i32 1, i32 %.op.op ; <i32> [#uses=1]
+ load i16* @g_39, align 2 ; <i16>:130 [#uses=1]
+ zext i16 %130 to i32 ; <i32>:131 [#uses=1]
+ icmp slt i32 %.354..lobit.not, %131 ; <i1>:132 [#uses=1]
+ zext i1 %132 to i32 ; <i32>:133 [#uses=1]
+ add i32 %p_49_addr.0, 1 ; <i32>:134 [#uses=2]
+ icmp sgt i32 %134, -1 ; <i1>:135 [#uses=1]
+ br i1 %135, label %bb248, label %bb307
+
+bb307: ; preds = %bb284
+ tail call i32 @func_103( i16 zeroext 0 ) nounwind ; <i32>:136 [#uses=0]
+ ret i32 %40
+
+bb311.loopexit.split: ; preds = %bb272.thread
+ store i32 1, i32* @g_82
+ ret i32 1
+
+bb311: ; preds = %bb223, %bb202
+ %.0 = phi i32 [ 1, %bb202 ], [ 0, %bb223 ] ; <i32> [#uses=1]
+ ret i32 %.0
+}
+
+declare i32 @func_25(i8 zeroext ) nounwind
+
+declare i32 @func_55(i32, i16 zeroext , i16 zeroext ) nounwind
+
+declare i32 @func_63(i16 signext ) nounwind
+
+declare i32 @func_74(i16 zeroext , i8 zeroext , i16 zeroext , i16 zeroext ) nounwind
+
+declare i32 @func_84(i32, i16 zeroext , i16 zeroext ) nounwind
+
+declare i32 @func_103(i16 zeroext ) nounwind
+
+declare i32 @func_124(i32) nounwind
+
+declare i32 @func_128(i32) nounwind
+
+declare i32 @func_116(i8 zeroext ) nounwind
+
+declare i32 @func_112(i32, i16 zeroext ) nounwind
diff --git a/test/Transforms/LoopStrengthReduce/pr3086.ll b/test/Transforms/LoopStrengthReduce/pr3086.ll
new file mode 100644
index 0000000000..599633a11f
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/pr3086.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -loop-reduce
+; RUN: opt < %s -analyze -scalar-evolution
+; PR 3086
+
+ %struct.Cls = type { i32, i8, [2 x %struct.Cls*], [2 x %struct.Lit*] }
+ %struct.Lit = type { i8 }
+
+define fastcc i64 @collect_clauses() nounwind {
+entry:
+ br label %bb11
+
+bb5: ; preds = %bb9
+ %0 = load %struct.Lit** %storemerge, align 8 ; <%struct.Lit*> [#uses=0]
+ %indvar.next8 = add i64 %storemerge.rec, 1 ; <i64> [#uses=1]
+ br label %bb9
+
+bb9: ; preds = %bb22, %bb5
+ %storemerge.rec = phi i64 [ %indvar.next8, %bb5 ], [ 0, %bb22 ] ; <i64> [#uses=2]
+ %storemerge = getelementptr %struct.Lit** null, i64 %storemerge.rec ; <%struct.Lit**> [#uses=2]
+ %1 = icmp ugt %struct.Lit** null, %storemerge ; <i1> [#uses=1]
+ br i1 %1, label %bb5, label %bb22
+
+bb11: ; preds = %bb22, %entry
+ %2 = load %struct.Cls** null, align 8 ; <%struct.Cls*> [#uses=0]
+ br label %bb22
+
+bb22: ; preds = %bb11, %bb9
+ br i1 false, label %bb11, label %bb9
+}
diff --git a/test/Transforms/LoopStrengthReduce/pr3399.ll b/test/Transforms/LoopStrengthReduce/pr3399.ll
new file mode 100644
index 0000000000..b809007fea
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/pr3399.ll
@@ -0,0 +1,32 @@
+; RUN: opt < %s -loop-reduce | llvm-dis
+; PR3399
+
+@g_53 = external global i32 ; <i32*> [#uses=1]
+
+define i32 @foo() nounwind {
+bb5.thread:
+ br label %bb
+
+bb: ; preds = %bb5, %bb5.thread
+ %indvar = phi i32 [ 0, %bb5.thread ], [ %indvar.next, %bb5 ] ; <i32> [#uses=2]
+ br i1 false, label %bb5, label %bb1
+
+bb1: ; preds = %bb
+ %l_2.0.reg2mem.0 = sub i32 0, %indvar ; <i32> [#uses=1]
+ %0 = volatile load i32* @g_53, align 4 ; <i32> [#uses=1]
+ %1 = trunc i32 %l_2.0.reg2mem.0 to i16 ; <i16> [#uses=1]
+ %2 = trunc i32 %0 to i16 ; <i16> [#uses=1]
+ %3 = mul i16 %2, %1 ; <i16> [#uses=1]
+ %4 = icmp eq i16 %3, 0 ; <i1> [#uses=1]
+ br i1 %4, label %bb7, label %bb2
+
+bb2: ; preds = %bb2, %bb1
+ br label %bb2
+
+bb5: ; preds = %bb
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ br label %bb
+
+bb7: ; preds = %bb1
+ ret i32 1
+}
diff --git a/test/Transforms/LoopStrengthReduce/pr3571.ll b/test/Transforms/LoopStrengthReduce/pr3571.ll
new file mode 100644
index 0000000000..9ad27d5ff1
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/pr3571.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -loop-reduce | llvm-dis
+; PR3571
+
+target triple = "i386-mingw32"
+define void @_ZNK18qdesigner_internal10TreeWidget12drawBranchesEP8QPainterRK5QRectRK11QModelIndex() nounwind {
+entry:
+ br label %_ZNK11QModelIndex7isValidEv.exit.i
+
+bb.i: ; preds = %_ZNK11QModelIndex7isValidEv.exit.i
+ %indvar.next = add i32 %result.0.i, 1 ; <i32> [#uses=1]
+ br label %_ZNK11QModelIndex7isValidEv.exit.i
+
+_ZNK11QModelIndex7isValidEv.exit.i: ; preds = %bb.i, %entry
+ %result.0.i = phi i32 [ 0, %entry ], [ %indvar.next, %bb.i ] ; <i32> [#uses=2]
+ %0 = load i32** null, align 4 ; <%struct.QAbstractItemDelegate*> [#uses=0]
+ br i1 false, label %_ZN18qdesigner_internalL5levelEP18QAbstractItemModelRK11QModelIndex.exit, label %bb.i
+
+_ZN18qdesigner_internalL5levelEP18QAbstractItemModelRK11QModelIndex.exit: ; preds = %_ZNK11QModelIndex7isValidEv.exit.i
+ %1 = call i32 @_ZNK9QTreeView11indentationEv(i32* null) nounwind ; <i32> [#uses=1]
+ %2 = mul i32 %1, %result.0.i ; <i32> [#uses=1]
+ %3 = add i32 %2, -2 ; <i32> [#uses=1]
+ %4 = add i32 %3, 0 ; <i32> [#uses=1]
+ store i32 %4, i32* null, align 8
+ unreachable
+}
+
+declare i32 @_ZNK9QTreeView11indentationEv(i32*)
diff --git a/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll b/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll
new file mode 100644
index 0000000000..c91f5cd4ca
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll
@@ -0,0 +1,18 @@
+; RUN: opt < %s -analyze -iv-users | grep {Stride i64 {3,+,2}<%loop>:}
+
+; The value of %r is dependent on a polynomial iteration expression.
+
+define i64 @foo(i64 %n) {
+entry:
+ br label %loop
+
+loop:
+ %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %loop ]
+ %indvar.next = add i64 %indvar, 1
+ %c = icmp eq i64 %indvar.next, %n
+ br i1 %c, label %exit, label %loop
+
+exit:
+ %r = mul i64 %indvar.next, %indvar.next
+ ret i64 %r
+}
diff --git a/test/Transforms/LoopStrengthReduce/related_indvars.ll b/test/Transforms/LoopStrengthReduce/related_indvars.ll
new file mode 100644
index 0000000000..12942bf10a
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/related_indvars.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -loop-reduce -S | grep phi | count 1
+
+; This should only result in one PHI node!
+
+; void foo(double *D, double *E, double F) {
+; while (D != E)
+; *D++ = F;
+; }
+
+define void @foo(double* %D, double* %E, double %F) nounwind {
+entry:
+ %tmp.24 = icmp eq double* %D, %E ; <i1> [#uses=1]
+ br i1 %tmp.24, label %return, label %no_exit
+no_exit: ; preds = %no_exit, %entry
+ %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %no_exit ] ; <i32> [#uses=2]
+ %D_addr.0.0.rec = bitcast i32 %indvar to i32 ; <i32> [#uses=2]
+ %D_addr.0.0 = getelementptr double* %D, i32 %D_addr.0.0.rec ; <double*> [#uses=1]
+ %inc.rec = add i32 %D_addr.0.0.rec, 1 ; <i32> [#uses=1]
+ %inc = getelementptr double* %D, i32 %inc.rec ; <double*> [#uses=1]
+ store double %F, double* %D_addr.0.0
+ %tmp.2 = icmp eq double* %inc, %E ; <i1> [#uses=1]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ br i1 %tmp.2, label %return, label %no_exit
+return: ; preds = %no_exit, %entry
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/remove_indvar.ll b/test/Transforms/LoopStrengthReduce/remove_indvar.ll
new file mode 100644
index 0000000000..53f4b9d5b9
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/remove_indvar.ll
@@ -0,0 +1,19 @@
+; Check that this test makes INDVAR and related stuff dead.
+; RUN: opt < %s -loop-reduce -S | not grep INDVAR
+
+declare i1 @pred()
+
+define void @test(i32* %P) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %STRRED = getelementptr i32* %P, i32 %INDVAR ; <i32*> [#uses=1]
+ store i32 0, i32* %STRRED
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ %cond = call i1 @pred( ) ; <i1> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/share_code_in_preheader.ll b/test/Transforms/LoopStrengthReduce/share_code_in_preheader.ll
new file mode 100644
index 0000000000..412a716bc4
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/share_code_in_preheader.ll
@@ -0,0 +1,27 @@
+; RUN: opt < %s -loop-reduce -S | grep mul | count 1
+; LSR should not make two copies of the Q*L expression in the preheader!
+
+define i8 @test(i8* %A, i8* %B, i32 %L, i32 %Q, i32 %N.s) {
+entry:
+ %tmp.6 = mul i32 %Q, %L ; <i32> [#uses=1]
+ %N = bitcast i32 %N.s to i32 ; <i32> [#uses=1]
+ br label %no_exit
+no_exit: ; preds = %no_exit, %entry
+ %indvar.ui = phi i32 [ 0, %entry ], [ %indvar.next, %no_exit ] ; <i32> [#uses=2]
+ %Sum.0.0 = phi i8 [ 0, %entry ], [ %tmp.21, %no_exit ] ; <i8> [#uses=1]
+ %indvar = bitcast i32 %indvar.ui to i32 ; <i32> [#uses=1]
+ %N_addr.0.0 = sub i32 %N.s, %indvar ; <i32> [#uses=1]
+ %tmp.8 = add i32 %N_addr.0.0, %tmp.6 ; <i32> [#uses=2]
+ %tmp.9 = getelementptr i8* %A, i32 %tmp.8 ; <i8*> [#uses=1]
+ %tmp.10 = load i8* %tmp.9 ; <i8> [#uses=1]
+ %tmp.17 = getelementptr i8* %B, i32 %tmp.8 ; <i8*> [#uses=1]
+ %tmp.18 = load i8* %tmp.17 ; <i8> [#uses=1]
+ %tmp.19 = sub i8 %tmp.10, %tmp.18 ; <i8> [#uses=1]
+ %tmp.21 = add i8 %tmp.19, %Sum.0.0 ; <i8> [#uses=2]
+ %indvar.next = add i32 %indvar.ui, 1 ; <i32> [#uses=2]
+ %exitcond = icmp eq i32 %indvar.next, %N ; <i1> [#uses=1]
+ br i1 %exitcond, label %loopexit, label %no_exit
+loopexit: ; preds = %no_exit
+ ret i8 %tmp.21
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/share_ivs.ll b/test/Transforms/LoopStrengthReduce/share_ivs.ll
new file mode 100644
index 0000000000..0459bc849b
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/share_ivs.ll
@@ -0,0 +1,24 @@
+; RUN: opt < %s -loop-reduce -S | grep phi | count 1
+
+; This testcase should have ONE stride 18 indvar, the other use should have a
+; loop invariant value (B) added to it inside of the loop, instead of having
+; a whole indvar based on B for it.
+
+declare i1 @cond(i32)
+
+define void @test(i32 %B) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %IV = phi i32 [ 0, %0 ], [ %IVn, %Loop ] ; <i32> [#uses=3]
+ %C = mul i32 %IV, 18 ; <i32> [#uses=1]
+ %D = mul i32 %IV, 18 ; <i32> [#uses=1]
+ %E = add i32 %D, %B ; <i32> [#uses=1]
+ %cnd = call i1 @cond( i32 %E ) ; <i1> [#uses=1]
+ call i1 @cond( i32 %C ) ; <i1>:1 [#uses=0]
+ %IVn = add i32 %IV, 1 ; <i32> [#uses=1]
+ br i1 %cnd, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll b/test/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll
new file mode 100644
index 0000000000..a99a823a3b
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: grep {add i32 %lsr.iv.next, 1}
+;
+; Make sure that the use of the IV outside of the loop (the store) uses the
+; post incremented value of the IV, not the preincremented value. This
+; prevents the loop from having to keep the post and pre-incremented value
+; around for the duration of the loop, adding a copy and an extra register
+; to the loop.
+
+declare i1 @pred(i32)
+
+define void @test([700 x i32]* %nbeaux_.0__558, i32* %i_.16574) {
+then.0:
+ br label %no_exit.2
+no_exit.2: ; preds = %no_exit.2, %then.0
+ %indvar630.ui = phi i32 [ 0, %then.0 ], [ %indvar.next631, %no_exit.2 ] ; <i32> [#uses=3]
+ %indvar630 = bitcast i32 %indvar630.ui to i32 ; <i32> [#uses=2]
+ %gep.upgrd.1 = zext i32 %indvar630.ui to i64 ; <i64> [#uses=1]
+ %tmp.38 = getelementptr [700 x i32]* %nbeaux_.0__558, i32 0, i64 %gep.upgrd.1 ; <i32*> [#uses=1]
+ store i32 0, i32* %tmp.38
+ %inc.2 = add i32 %indvar630, 2 ; <i32> [#uses=1]
+ %tmp.34 = call i1 @pred( i32 %indvar630 ) ; <i1> [#uses=1]
+ %indvar.next631 = add i32 %indvar630.ui, 1 ; <i32> [#uses=1]
+ br i1 %tmp.34, label %no_exit.2, label %loopexit.2.loopexit
+loopexit.2.loopexit: ; preds = %no_exit.2
+ store i32 %inc.2, i32* %i_.16574
+ ret void
+}
+
diff --git a/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll
new file mode 100644
index 0000000000..0a9fab0d5e
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll
@@ -0,0 +1,41 @@
+; Base should not be i*3, it should be i*2.
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: not grep {mul.*%i, 3}
+
+; Indvar should not start at zero:
+; RUN: opt < %s -loop-reduce -S | \
+; RUN: not grep {phi i32 .* 0}
+; END.
+
+; mul uint %i, 3
+
+target datalayout = "e-p:32:32"
+target triple = "i686-apple-darwin8"
+@flags2 = external global [8193 x i8], align 32 ; <[8193 x i8]*> [#uses=1]
+
+define void @foo(i32 %k, i32 %i.s) {
+entry:
+ %i = bitcast i32 %i.s to i32 ; <i32> [#uses=2]
+ %k_addr.012 = shl i32 %i.s, 1 ; <i32> [#uses=1]
+ %tmp14 = icmp sgt i32 %k_addr.012, 8192 ; <i1> [#uses=1]
+ br i1 %tmp14, label %return, label %bb.preheader
+bb.preheader: ; preds = %entry
+ %tmp. = shl i32 %i, 1 ; <i32> [#uses=1]
+ br label %bb
+bb: ; preds = %bb, %bb.preheader
+ %indvar = phi i32 [ %indvar.next, %bb ], [ 0, %bb.preheader ] ; <i32> [#uses=2]
+ %tmp.15 = mul i32 %indvar, %i ; <i32> [#uses=1]
+ %tmp.16 = add i32 %tmp.15, %tmp. ; <i32> [#uses=2]
+ %k_addr.0.0 = bitcast i32 %tmp.16 to i32 ; <i32> [#uses=1]
+ %gep.upgrd.1 = zext i32 %tmp.16 to i64 ; <i64> [#uses=1]
+ %tmp = getelementptr [8193 x i8]* @flags2, i32 0, i64 %gep.upgrd.1 ; <i8*> [#uses=1]
+ store i8 0, i8* %tmp
+ %k_addr.0 = add i32 %k_addr.0.0, %i.s ; <i32> [#uses=1]
+ %tmp.upgrd.2 = icmp sgt i32 %k_addr.0, 8192 ; <i1> [#uses=1]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
+ br i1 %tmp.upgrd.2, label %return.loopexit, label %bb
+return.loopexit: ; preds = %bb
+ br label %return
+return: ; preds = %return.loopexit, %entry
+ ret void
+}
diff --git a/test/Transforms/LoopStrengthReduce/variable_stride.ll b/test/Transforms/LoopStrengthReduce/variable_stride.ll
new file mode 100644
index 0000000000..7c0f053e4c
--- /dev/null
+++ b/test/Transforms/LoopStrengthReduce/variable_stride.ll
@@ -0,0 +1,18 @@
+; Check that variable strides are reduced to adds instead of multiplies.
+; RUN: opt < %s -loop-reduce -S | not grep mul
+
+declare i1 @pred(i32)
+
+define void @test([10000 x i32]* %P, i32 %STRIDE) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %INDVAR = phi i32 [ 0, %0 ], [ %INDVAR2, %Loop ] ; <i32> [#uses=2]
+ %Idx = mul i32 %INDVAR, %STRIDE ; <i32> [#uses=1]
+ %cond = call i1 @pred( i32 %Idx ) ; <i1> [#uses=1]
+ %INDVAR2 = add i32 %INDVAR, 1 ; <i32> [#uses=1]
+ br i1 %cond, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+