summaryrefslogtreecommitdiff
path: root/test/Transforms/LICM
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/LICM')
-rw-r--r--test/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll18
-rw-r--r--test/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll17
-rw-r--r--test/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll16
-rw-r--r--test/Transforms/LICM/2003-02-27-PreheaderProblem.ll24
-rw-r--r--test/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll15
-rw-r--r--test/Transforms/LICM/2003-02-28-PromoteDifferentType.ll15
-rw-r--r--test/Transforms/LICM/2003-05-02-LoadHoist.ll23
-rw-r--r--test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll26
-rw-r--r--test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll21
-rw-r--r--test/Transforms/LICM/2003-12-11-SinkingToPHI.ll16
-rw-r--r--test/Transforms/LICM/2003-12-13-VolatilePromote.ll16
-rw-r--r--test/Transforms/LICM/2004-09-14-AliasAnalysisInvalidate.ll19
-rw-r--r--test/Transforms/LICM/2004-11-17-UndefIndexCrash.ll20
-rw-r--r--test/Transforms/LICM/2005-03-24-LICM-Aggregate-Crash.ll9
-rw-r--r--test/Transforms/LICM/2006-09-12-DeadUserOfSunkInstr.ll148
-rw-r--r--test/Transforms/LICM/2007-05-22-VolatileSink.ll56
-rw-r--r--test/Transforms/LICM/2007-07-30-AliasSet.ll39
-rw-r--r--test/Transforms/LICM/2007-09-17-PromoteValue.ll61
-rw-r--r--test/Transforms/LICM/2007-09-24-PromoteNullValue.ll46
-rw-r--r--test/Transforms/LICM/2007-10-01-PromoteSafeValue.ll21
-rw-r--r--test/Transforms/LICM/2008-05-20-AliasSetVAArg.ll30
-rw-r--r--test/Transforms/LICM/2008-07-22-LoadGlobalConstant.ll23
-rw-r--r--test/Transforms/LICM/2009-03-25-AliasSetTracker.ll39
-rw-r--r--test/Transforms/LICM/Preserve-LCSSA.ll25
-rw-r--r--test/Transforms/LICM/basictest.ll15
-rw-r--r--test/Transforms/LICM/call_sink_const_function.ll17
-rw-r--r--test/Transforms/LICM/call_sink_pure_function.ll16
-rw-r--r--test/Transforms/LICM/dg.exp3
-rw-r--r--test/Transforms/LICM/no-preheader-test.ll20
-rw-r--r--test/Transforms/LICM/scalar_promote.ll35
-rw-r--r--test/Transforms/LICM/sink_critical_edge.ll16
-rw-r--r--test/Transforms/LICM/sink_inst.ll20
-rw-r--r--test/Transforms/LICM/sink_load.ll21
-rw-r--r--test/Transforms/LICM/sink_multiple.ll21
-rw-r--r--test/Transforms/LICM/sink_multiple_exits.ll24
-rw-r--r--test/Transforms/LICM/sink_only_some_exits.ll23
-rw-r--r--test/Transforms/LICM/sink_phi_node_use.ll21
-rw-r--r--test/Transforms/LICM/sink_trapping_inst.ll18
38 files changed, 1013 insertions, 0 deletions
diff --git a/test/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll b/test/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll
new file mode 100644
index 000000000000..cf0520617938
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll
@@ -0,0 +1,18 @@
+; RUN: llvm-as < %s | opt -basicaa -licm -disable-output
+
+;%MoveArray = external global [64 x ulong]
+
+define void @InitMoveArray() {
+bb3:
+ %X = alloca [2 x i64] ; <[2 x i64]*> [#uses=1]
+ br i1 false, label %bb13, label %bb4
+bb4: ; preds = %bb3
+ %reg3011 = getelementptr [2 x i64]* %X, i64 0, i64 0 ; <i64*> [#uses=1]
+ br label %bb8
+bb8: ; preds = %bb8, %bb4
+ store i64 0, i64* %reg3011
+ br i1 false, label %bb8, label %bb13
+bb13: ; preds = %bb8, %bb3
+ ret void
+}
+
diff --git a/test/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll b/test/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll
new file mode 100644
index 000000000000..bf209eaa479f
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll
@@ -0,0 +1,17 @@
+; Exit blocks need to be updated for all nested loops...
+
+; RUN: llvm-as < %s | opt -loopsimplify
+
+define i32 @yyparse() {
+bb0:
+ br i1 false, label %UnifiedExitNode, label %bb19
+bb19: ; preds = %bb28, %bb0
+ br i1 false, label %bb28, label %UnifiedExitNode
+bb28: ; preds = %bb32, %bb19
+ br i1 false, label %bb32, label %bb19
+bb32: ; preds = %bb28
+ br i1 false, label %UnifiedExitNode, label %bb28
+UnifiedExitNode: ; preds = %bb32, %bb19, %bb0
+ ret i32 0
+}
+
diff --git a/test/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll b/test/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll
new file mode 100644
index 000000000000..4b51a3be4b06
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll
@@ -0,0 +1,16 @@
+; This testcase fails because preheader insertion is not updating exit node
+; information for loops.
+
+; RUN: llvm-as < %s | opt -licm
+
+define i32 @main(i32 %argc, i8** %argv) {
+bb0:
+ br i1 false, label %bb7, label %bb5
+bb5: ; preds = %bb5, %bb0
+ br i1 false, label %bb5, label %bb7
+bb7: ; preds = %bb7, %bb5, %bb0
+ br i1 false, label %bb7, label %bb10
+bb10: ; preds = %bb7
+ ret i32 0
+}
+
diff --git a/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll b/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll
new file mode 100644
index 000000000000..18b86064ed04
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll
@@ -0,0 +1,24 @@
+; Here we have a case where there are two loops and LICM is hoisting an
+; instruction from one loop into the other loop! This is obviously bad and
+; happens because preheader insertion doesn't insert a preheader for this
+; case... bad.
+
+; RUN: llvm-as < %s | opt -licm -loop-deletion -simplifycfg | llvm-dis | \
+; RUN: not grep {br }
+
+define i32 @main(i32 %argc) {
+; <label>:0
+ br label %bb5
+bb5: ; preds = %bb5, %0
+ %I = phi i32 [ 0, %0 ], [ %I2, %bb5 ] ; <i32> [#uses=1]
+ %I2 = add i32 %I, 1 ; <i32> [#uses=2]
+ %c = icmp eq i32 %I2, 10 ; <i1> [#uses=1]
+ br i1 %c, label %bb5, label %bb8
+bb8: ; preds = %bb8, %bb5
+ %cann-indvar = phi i32 [ 0, %bb8 ], [ 0, %bb5 ] ; <i32> [#uses=0]
+ %X = add i32 %argc, %argc ; <i32> [#uses=1]
+ br i1 false, label %bb8, label %bb10
+bb10: ; preds = %bb8
+ ret i32 %X
+}
+
diff --git a/test/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll b/test/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll
new file mode 100644
index 000000000000..7ce164ec237f
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll
@@ -0,0 +1,15 @@
+; LICM is adding stores before phi nodes. bad.
+
+; RUN: llvm-as < %s | opt -licm
+
+define i1 @test(i1 %c) {
+; <label>:0
+ br i1 %c, label %Loop, label %Out
+Loop: ; preds = %Loop, %0
+ store i32 0, i32* null
+ br i1 %c, label %Loop, label %Out
+Out: ; preds = %Loop, %0
+ %X = phi i1 [ %c, %0 ], [ true, %Loop ] ; <i1> [#uses=1]
+ ret i1 %X
+}
+
diff --git a/test/Transforms/LICM/2003-02-28-PromoteDifferentType.ll b/test/Transforms/LICM/2003-02-28-PromoteDifferentType.ll
new file mode 100644
index 000000000000..849ecd7cb1bb
--- /dev/null
+++ b/test/Transforms/LICM/2003-02-28-PromoteDifferentType.ll
@@ -0,0 +1,15 @@
+; Test that hoisting is disabled for pointers of different types...
+;
+; RUN: llvm-as < %s | opt -licm
+
+define void @test(i32* %P) {
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ store i32 5, i32* %P
+ %P2 = bitcast i32* %P to i8* ; <i8*> [#uses=1]
+ store i8 4, i8* %P2
+ br i1 true, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LICM/2003-05-02-LoadHoist.ll b/test/Transforms/LICM/2003-05-02-LoadHoist.ll
new file mode 100644
index 000000000000..7b58535972e5
--- /dev/null
+++ b/test/Transforms/LICM/2003-05-02-LoadHoist.ll
@@ -0,0 +1,23 @@
+; This testcase tests for a problem where LICM hoists loads out of a loop
+; despite the fact that calls to unknown functions may modify what is being
+; loaded from. Basically if the load gets hoisted, the subtract gets turned
+; into a constant zero.
+;
+; RUN: llvm-as < %s | opt -licm -gvn -instcombine | llvm-dis | grep load
+
+@X = global i32 7 ; <i32*> [#uses=2]
+
+declare void @foo()
+
+define i32 @test(i1 %c) {
+ %A = load i32* @X ; <i32> [#uses=1]
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ call void @foo( )
+ ;; Should not hoist this load!
+ %B = load i32* @X ; <i32> [#uses=1]
+ br i1 %c, label %Loop, label %Out
+Out: ; preds = %Loop
+ %C = sub i32 %A, %B ; <i32> [#uses=1]
+ ret i32 %C
+}
diff --git a/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll b/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll
new file mode 100644
index 000000000000..a00eb8c7a63c
--- /dev/null
+++ b/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll
@@ -0,0 +1,26 @@
+; This testcase tests for a problem where LICM hoists
+; potentially trapping instructions when they are not guaranteed to execute.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext "IfUnEqual" 2 | grep div
+
+@X = global i32 0 ; <i32*> [#uses=1]
+
+declare void @foo()
+
+define i32 @test(i1 %c) {
+ %A = load i32* @X ; <i32> [#uses=2]
+ br label %Loop
+Loop: ; preds = %LoopTail, %0
+ call void @foo( )
+ br i1 %c, label %LoopTail, label %IfUnEqual
+IfUnEqual: ; preds = %Loop
+ %B1 = sdiv i32 4, %A ; <i32> [#uses=1]
+ br label %LoopTail
+LoopTail: ; preds = %IfUnEqual, %Loop
+ %B = phi i32 [ 0, %Loop ], [ %B1, %IfUnEqual ] ; <i32> [#uses=1]
+ br i1 %c, label %Loop, label %Out
+Out: ; preds = %LoopTail
+ %C = sub i32 %A, %B ; <i32> [#uses=1]
+ ret i32 %C
+}
+
diff --git a/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll b/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll
new file mode 100644
index 000000000000..59cc0d662071
--- /dev/null
+++ b/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll
@@ -0,0 +1,21 @@
+; This testcase tests to make sure a trapping instruction is hoisted when
+; it is guaranteed to execute.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext "test" 2 | grep div
+
+@X = global i32 0 ; <i32*> [#uses=1]
+
+declare void @foo(i32)
+
+define i32 @test(i1 %c) {
+ %A = load i32* @X ; <i32> [#uses=2]
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ ;; Should have hoisted this div!
+ %B = sdiv i32 4, %A ; <i32> [#uses=2]
+ call void @foo( i32 %B )
+ br i1 %c, label %Loop, label %Out
+Out: ; preds = %Loop
+ %C = sub i32 %A, %B ; <i32> [#uses=1]
+ ret i32 %C
+}
diff --git a/test/Transforms/LICM/2003-12-11-SinkingToPHI.ll b/test/Transforms/LICM/2003-12-11-SinkingToPHI.ll
new file mode 100644
index 000000000000..e491c9aee479
--- /dev/null
+++ b/test/Transforms/LICM/2003-12-11-SinkingToPHI.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -licm | lli
+
+define i32 @main() {
+entry:
+ br label %Loop
+Loop: ; preds = %LoopCont, %entry
+ br i1 true, label %LoopCont, label %Out
+LoopCont: ; preds = %Loop
+ %X = add i32 1, 0 ; <i32> [#uses=1]
+ br i1 true, label %Out, label %Loop
+Out: ; preds = %LoopCont, %Loop
+ %V = phi i32 [ 2, %Loop ], [ %X, %LoopCont ] ; <i32> [#uses=1]
+ %V2 = sub i32 %V, 1 ; <i32> [#uses=1]
+ ret i32 %V2
+}
+
diff --git a/test/Transforms/LICM/2003-12-13-VolatilePromote.ll b/test/Transforms/LICM/2003-12-13-VolatilePromote.ll
new file mode 100644
index 000000000000..85c93c62bf5c
--- /dev/null
+++ b/test/Transforms/LICM/2003-12-13-VolatilePromote.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext volatile 1 | grep Loop
+
+@X = global i32 7 ; <i32*> [#uses=2]
+
+define void @testfunc(i32 %i) {
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ ; Should not promote this to a register
+ %x = volatile load i32* @X ; <i32> [#uses=1]
+ %x2 = add i32 %x, 1 ; <i32> [#uses=1]
+ store i32 %x2, i32* @X
+ br i1 true, label %Out, label %Loop
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LICM/2004-09-14-AliasAnalysisInvalidate.ll b/test/Transforms/LICM/2004-09-14-AliasAnalysisInvalidate.ll
new file mode 100644
index 000000000000..b9c9eb373999
--- /dev/null
+++ b/test/Transforms/LICM/2004-09-14-AliasAnalysisInvalidate.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -globalsmodref-aa -licm -disable-output
+
+@PL_regcomp_parse = internal global i8* null ; <i8**> [#uses=2]
+
+define void @test() {
+ br label %Outer
+Outer: ; preds = %Next, %0
+ br label %Inner
+Inner: ; preds = %Inner, %Outer
+ %tmp.114.i.i.i = load i8** @PL_regcomp_parse ; <i8*> [#uses=1]
+ %tmp.115.i.i.i = load i8* %tmp.114.i.i.i ; <i8> [#uses=0]
+ store i8* null, i8** @PL_regcomp_parse
+ br i1 false, label %Inner, label %Next
+Next: ; preds = %Inner
+ br i1 false, label %Outer, label %Exit
+Exit: ; preds = %Next
+ ret void
+}
+
diff --git a/test/Transforms/LICM/2004-11-17-UndefIndexCrash.ll b/test/Transforms/LICM/2004-11-17-UndefIndexCrash.ll
new file mode 100644
index 000000000000..9a53d95996a7
--- /dev/null
+++ b/test/Transforms/LICM/2004-11-17-UndefIndexCrash.ll
@@ -0,0 +1,20 @@
+; RUN: llvm-as < %s | opt -licm -disable-output
+ %struct.roadlet = type { i8*, %struct.vehicle*, [8 x %struct.roadlet*], [8 x %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)*] }
+ %struct.vehicle = type { %struct.roadlet*, i8*, i32, i32, %union.._631., i32 }
+ %union.._631. = type { i32 }
+
+declare %struct.roadlet* @_Z11return_nullP7roadletP7vehicle9direction(%struct.roadlet*, %struct.vehicle*, i32)
+
+declare %struct.roadlet* @_Z14lane_switch_okP7roadletP7vehicle9direction(%struct.roadlet*, %struct.vehicle*, i32)
+
+define void @main() {
+__main.entry:
+ br label %invoke_cont.3
+invoke_cont.3: ; preds = %invoke_cont.3, %__main.entry
+ %tmp.34.i.i502.7 = getelementptr %struct.roadlet* null, i32 0, i32 3, i32 7 ; <%struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)**> [#uses=1]
+ store %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)* @_Z11return_nullP7roadletP7vehicle9direction, %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)** %tmp.34.i.i502.7
+ store %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)* @_Z14lane_switch_okP7roadletP7vehicle9direction, %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)** null
+ %tmp.4.i.i339 = getelementptr %struct.roadlet* null, i32 0, i32 3, i32 undef ; <%struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)**> [#uses=1]
+ store %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)* @_Z11return_nullP7roadletP7vehicle9direction, %struct.roadlet* (%struct.roadlet*, %struct.vehicle*, i32)** %tmp.4.i.i339
+ br label %invoke_cont.3
+}
diff --git a/test/Transforms/LICM/2005-03-24-LICM-Aggregate-Crash.ll b/test/Transforms/LICM/2005-03-24-LICM-Aggregate-Crash.ll
new file mode 100644
index 000000000000..b001cd0d5cd2
--- /dev/null
+++ b/test/Transforms/LICM/2005-03-24-LICM-Aggregate-Crash.ll
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | opt -licm -disable-output
+
+define void @test({ i32 }* %P) {
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ free { i32 }* %P
+ br label %Loop
+}
+
diff --git a/test/Transforms/LICM/2006-09-12-DeadUserOfSunkInstr.ll b/test/Transforms/LICM/2006-09-12-DeadUserOfSunkInstr.ll
new file mode 100644
index 000000000000..c2c4bcb4ab0b
--- /dev/null
+++ b/test/Transforms/LICM/2006-09-12-DeadUserOfSunkInstr.ll
@@ -0,0 +1,148 @@
+; RUN: llvm-as < %s | opt -licm -disable-output
+; PR908
+; END.
+
+ %struct.alloc_chain = type { i8*, %struct.alloc_chain* }
+ %struct.oggpack_buffer = type { i32, i32, i8*, i8*, i32 }
+ %struct.vorbis_block = type { float**, %struct.oggpack_buffer, i32, i32, i32, i32, i32, i32, i64, i64, %struct.vorbis_dsp_state*, i8*, i32, i32, i32, %struct.alloc_chain*, i32, i32, i32, i32, i8* }
+ %struct.vorbis_dsp_state = type { i32, %struct.vorbis_info*, float**, float**, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64, i64, i64, i64, i64, i64, i8* }
+ %struct.vorbis_info = type { i32, i32, i32, i32, i32, i32, i32, i8* }
+
+define fastcc void @_01forward() {
+entry:
+ br i1 false, label %bb222.preheader, label %bb241
+cond_true67: ; preds = %cond_true87
+ br label %cond_next80
+cond_next80: ; preds = %cond_true87, %cond_true67
+ br label %bb83
+bb83.preheader: ; preds = %cond_true226
+ br i1 false, label %bb83.us.preheader, label %bb83.preheader1
+bb83.us.preheader: ; preds = %bb83.preheader
+ br label %bb83.us
+bb83.us: ; preds = %cond_next80.us, %bb83.us.preheader
+ br i1 false, label %cond_true87.us, label %cond_next92.loopexit2
+cond_next80.us: ; preds = %bb59.loopexit.us, %cond_true67.us
+ br label %bb83.us
+cond_true67.us: ; preds = %bb59.loopexit.us
+ br label %cond_next80.us
+cond_next.us: ; preds = %cond_true56.us, %cond_true38.us
+ br i1 false, label %cond_true56.us, label %bb59.loopexit.us
+cond_true38.us: ; preds = %cond_true56.us
+ br label %cond_next.us
+cond_true56.us: ; preds = %cond_true87.us, %cond_next.us
+ br i1 false, label %cond_true38.us, label %cond_next.us
+cond_true87.us: ; preds = %bb83.us
+ br label %cond_true56.us
+bb59.loopexit.us: ; preds = %cond_next.us
+ br i1 false, label %cond_true67.us, label %cond_next80.us
+bb83.preheader1: ; preds = %bb83.preheader
+ br label %bb83
+bb83: ; preds = %bb83.preheader1, %cond_next80
+ br i1 false, label %cond_next92.loopexit, label %cond_true87
+cond_true87: ; preds = %bb83
+ br i1 false, label %cond_true67, label %cond_next80
+cond_next92.loopexit: ; preds = %bb83
+ br label %cond_next92
+cond_next92.loopexit2: ; preds = %bb83.us
+ br label %cond_next92
+cond_next92: ; preds = %cond_true226, %cond_next92.loopexit2, %cond_next92.loopexit
+ br i1 false, label %cond_true218.loopexit, label %bb222
+cond_true139: ; preds = %cond_true202
+ br i1 false, label %cond_next195, label %cond_true155
+cond_true155: ; preds = %cond_true139
+ br i1 false, label %cond_true249.i.preheader, label %_encodepart.exit
+cond_true.i: ; preds = %cond_true115.i
+ br i1 false, label %bb60.i.preheader, label %cond_next97.i
+bb60.i.preheader: ; preds = %cond_true.i
+ br label %bb60.i
+bb60.i: ; preds = %cond_true63.i, %bb60.i.preheader
+ br i1 false, label %cond_true63.i, label %cond_next97.i.loopexit
+cond_true63.i: ; preds = %bb60.i
+ br i1 false, label %bb60.i, label %cond_next97.i.loopexit
+bb86.i.preheader: ; preds = %cond_true115.i
+ br label %bb86.i
+bb86.i: ; preds = %cond_true93.i, %bb86.i.preheader
+ br i1 false, label %cond_true93.i, label %cond_next97.i.loopexit3
+cond_true93.i: ; preds = %bb86.i
+ br i1 false, label %cond_next97.i.loopexit3, label %bb86.i
+cond_next97.i.loopexit: ; preds = %cond_true63.i, %bb60.i
+ br label %cond_next97.i
+cond_next97.i.loopexit3: ; preds = %cond_true93.i, %bb86.i
+ br label %cond_next97.i
+cond_next97.i: ; preds = %cond_next97.i.loopexit3, %cond_next97.i.loopexit, %cond_true.i
+ br i1 false, label %bb118.i.loopexit, label %cond_true115.i
+cond_true115.i.preheader: ; preds = %cond_true249.i
+ br label %cond_true115.i
+cond_true115.i: ; preds = %cond_true115.i.preheader, %cond_next97.i
+ br i1 false, label %cond_true.i, label %bb86.i.preheader
+bb118.i.loopexit: ; preds = %cond_next97.i
+ br label %bb118.i
+bb118.i: ; preds = %cond_true249.i, %bb118.i.loopexit
+ br i1 false, label %cond_next204.i, label %cond_true128.i
+cond_true128.i: ; preds = %bb118.i
+ br i1 false, label %cond_true199.i.preheader, label %cond_next204.i
+cond_true199.i.preheader: ; preds = %cond_true128.i
+ br label %cond_true199.i
+cond_true199.i.us: ; No predecessors!
+ br i1 false, label %cond_true167.i.us, label %cond_next187.i.us
+cond_next187.i.us: ; preds = %bb170.i.loopexit.us, %bb170.i.us.cond_next187.i.us_crit_edge, %cond_true199.i.us
+ unreachable
+bb170.i.us.cond_next187.i.us_crit_edge: ; preds = %bb170.i.loopexit.us
+ br label %cond_next187.i.us
+cond_true167.i.us: ; preds = %cond_true167.i.us, %cond_true199.i.us
+ br i1 false, label %cond_true167.i.us, label %bb170.i.loopexit.us
+bb170.i.loopexit.us: ; preds = %cond_true167.i.us
+ br i1 false, label %cond_next187.i.us, label %bb170.i.us.cond_next187.i.us_crit_edge
+cond_true199.i: ; preds = %cond_true199.i, %cond_true199.i.preheader
+ br i1 false, label %cond_next204.i.loopexit, label %cond_true199.i
+cond_next204.i.loopexit: ; preds = %cond_true199.i
+ br label %cond_next204.i
+cond_next204.i: ; preds = %cond_next204.i.loopexit, %cond_true128.i, %bb118.i
+ br label %bb233.i
+cond_true230.i: ; No predecessors!
+ %exitcond155 = icmp eq i32 0, %tmp16.i ; <i1> [#uses=0]
+ unreachable
+bb233.i: ; preds = %cond_next204.i
+ br i1 false, label %_encodepart.exit.loopexit, label %cond_true249.i
+cond_true249.i.preheader: ; preds = %cond_true155
+ br label %cond_true249.i
+cond_true249.i: ; preds = %cond_true249.i.preheader, %bb233.i
+ %tmp16.i = bitcast i32 0 to i32 ; <i32> [#uses=1]
+ br i1 false, label %cond_true115.i.preheader, label %bb118.i
+_encodepart.exit.loopexit: ; preds = %bb233.i
+ br label %_encodepart.exit
+_encodepart.exit: ; preds = %_encodepart.exit.loopexit, %cond_true155
+ br label %cond_next195
+cond_next195: ; preds = %cond_true202, %_encodepart.exit, %cond_true139
+ br i1 false, label %bb205.loopexit, label %cond_true202
+cond_true202.preheader: ; preds = %cond_true218
+ br label %cond_true202
+cond_true202: ; preds = %cond_true202.preheader, %cond_next195
+ br i1 false, label %cond_next195, label %cond_true139
+bb205.loopexit: ; preds = %cond_next195
+ br label %bb205
+bb205: ; preds = %cond_true218, %bb205.loopexit
+ br i1 false, label %cond_true218, label %bb222.outer105.loopexit
+cond_true218.loopexit: ; preds = %cond_next92
+ br label %cond_true218
+cond_true218: ; preds = %cond_true218.loopexit, %bb205
+ br i1 false, label %cond_true202.preheader, label %bb205
+bb222.preheader: ; preds = %entry
+ br label %bb222.outer
+bb222.outer: ; preds = %bb229, %bb222.preheader
+ br label %bb222.outer105
+bb222.outer105.loopexit: ; preds = %bb205
+ br label %bb222.outer105
+bb222.outer105: ; preds = %bb222.outer105.loopexit, %bb222.outer
+ br label %bb222
+bb222: ; preds = %bb222.outer105, %cond_next92
+ br i1 false, label %cond_true226, label %bb229
+cond_true226: ; preds = %bb222
+ br i1 false, label %bb83.preheader, label %cond_next92
+bb229: ; preds = %bb222
+ br i1 false, label %bb222.outer, label %bb241.loopexit
+bb241.loopexit: ; preds = %bb229
+ br label %bb241
+bb241: ; preds = %bb241.loopexit, %entry
+ ret void
+}
diff --git a/test/Transforms/LICM/2007-05-22-VolatileSink.ll b/test/Transforms/LICM/2007-05-22-VolatileSink.ll
new file mode 100644
index 000000000000..bf5d7bc09297
--- /dev/null
+++ b/test/Transforms/LICM/2007-05-22-VolatileSink.ll
@@ -0,0 +1,56 @@
+; RUN: llvm-as < %s | opt -licm | llvm-dis | grep {volatile store}
+; PR1435
+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-darwin8"
+
+define void @Transpose(i32* %DataIn, i32* %DataOut) {
+entry:
+ %buffer = alloca [64 x i32], align 16 ; <[64 x i32]*> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ br label %bb6
+
+bb: ; preds = %bb6
+ %tmp2 = volatile load i32* %DataIn ; <i32> [#uses=1]
+ %tmp3 = getelementptr [64 x i32]* %buffer, i32 0, i32 %i.0 ; <i32*> [#uses=1]
+ store i32 %tmp2, i32* %tmp3
+ %tmp5 = add i32 %i.0, 1 ; <i32> [#uses=1]
+ br label %bb6
+
+bb6: ; preds = %bb, %entry
+ %i.0 = phi i32 [ 0, %entry ], [ %tmp5, %bb ] ; <i32> [#uses=3]
+ %tmp8 = icmp sle i32 %i.0, 63 ; <i1> [#uses=1]
+ %tmp89 = zext i1 %tmp8 to i8 ; <i8> [#uses=1]
+ %toBool = icmp ne i8 %tmp89, 0 ; <i1> [#uses=1]
+ br i1 %toBool, label %bb, label %bb30
+
+bb12: ; preds = %bb22
+ %tmp14 = mul i32 %j.1, 8 ; <i32> [#uses=1]
+ %tmp16 = add i32 %tmp14, %i.1 ; <i32> [#uses=1]
+ %tmp17 = getelementptr [64 x i32]* %buffer, i32 0, i32 %tmp16 ; <i32*> [#uses=1]
+ %tmp18 = load i32* %tmp17 ; <i32> [#uses=1]
+ volatile store i32 %tmp18, i32* %DataOut
+ %tmp21 = add i32 %j.1, 1 ; <i32> [#uses=1]
+ br label %bb22
+
+bb22: ; preds = %bb30, %bb12
+ %j.1 = phi i32 [ %tmp21, %bb12 ], [ 0, %bb30 ] ; <i32> [#uses=4]
+ %tmp24 = icmp sle i32 %j.1, 7 ; <i1> [#uses=1]
+ %tmp2425 = zext i1 %tmp24 to i8 ; <i8> [#uses=1]
+ %toBool26 = icmp ne i8 %tmp2425, 0 ; <i1> [#uses=1]
+ br i1 %toBool26, label %bb12, label %bb27
+
+bb27: ; preds = %bb22
+ %tmp29 = add i32 %i.1, 1 ; <i32> [#uses=1]
+ br label %bb30
+
+bb30: ; preds = %bb27, %bb6
+ %j.0 = phi i32 [ %j.1, %bb27 ], [ undef, %bb6 ] ; <i32> [#uses=0]
+ %i.1 = phi i32 [ %tmp29, %bb27 ], [ 0, %bb6 ] ; <i32> [#uses=3]
+ %tmp32 = icmp sle i32 %i.1, 7 ; <i1> [#uses=1]
+ %tmp3233 = zext i1 %tmp32 to i8 ; <i8> [#uses=1]
+ %toBool34 = icmp ne i8 %tmp3233, 0 ; <i1> [#uses=1]
+ br i1 %toBool34, label %bb22, label %return
+
+return: ; preds = %bb30
+ ret void
+}
diff --git a/test/Transforms/LICM/2007-07-30-AliasSet.ll b/test/Transforms/LICM/2007-07-30-AliasSet.ll
new file mode 100644
index 000000000000..110d88449464
--- /dev/null
+++ b/test/Transforms/LICM/2007-07-30-AliasSet.ll
@@ -0,0 +1,39 @@
+; RUN: llvm-as < %s | opt -licm -loop-unswitch -disable-output
+ %struct.III_scalefac_t = type { [22 x i32], [13 x [3 x i32]] }
+ %struct.gr_info = type { i32, i32, i32, i32, i32, i32, i32, i32, [3 x i32], [3 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32*, [4 x i32] }
+
+define i32 @scale_bitcount_lsf(%struct.III_scalefac_t* %scalefac, %struct.gr_info* %cod_info) {
+entry:
+ br i1 false, label %bb28, label %bb133.preheader
+
+bb133.preheader: ; preds = %entry
+ ret i32 0
+
+bb28: ; preds = %entry
+ br i1 false, label %bb63.outer, label %bb79
+
+bb63.outer: ; preds = %bb73, %bb28
+ br i1 false, label %bb35, label %bb73
+
+bb35: ; preds = %cond_next60, %bb63.outer
+ %window.34 = phi i32 [ %tmp62, %cond_next60 ], [ 0, %bb63.outer ] ; <i32> [#uses=1]
+ %tmp44 = getelementptr [4 x i32]* null, i32 0, i32 0 ; <i32*> [#uses=1]
+ %tmp46 = load i32* %tmp44, align 4 ; <i32> [#uses=0]
+ br i1 false, label %cond_true50, label %cond_next60
+
+cond_true50: ; preds = %bb35
+ %tmp59 = getelementptr [4 x i32]* null, i32 0, i32 0 ; <i32*> [#uses=1]
+ store i32 0, i32* %tmp59, align 4
+ br label %cond_next60
+
+cond_next60: ; preds = %cond_true50, %bb35
+ %tmp62 = add i32 %window.34, 1 ; <i32> [#uses=1]
+ br i1 false, label %bb35, label %bb73
+
+bb73: ; preds = %cond_next60, %bb63.outer
+ %tmp76 = icmp slt i32 0, 0 ; <i1> [#uses=1]
+ br i1 %tmp76, label %bb63.outer, label %bb79
+
+bb79: ; preds = %bb73, %bb28
+ ret i32 0
+}
diff --git a/test/Transforms/LICM/2007-09-17-PromoteValue.ll b/test/Transforms/LICM/2007-09-17-PromoteValue.ll
new file mode 100644
index 000000000000..e9ba9e16318f
--- /dev/null
+++ b/test/Transforms/LICM/2007-09-17-PromoteValue.ll
@@ -0,0 +1,61 @@
+; ModuleID = 'PR1657.bc'
+; Do not promote getelementptr because it may exposes load from a null pointer
+; and store from a null pointer which are covered by
+; icmp eq %struct.decision* null, null condition.
+; RUN: llvm-as < %s | opt -licm | llvm-dis | not grep promoted
+ %struct.decision = type { i8, %struct.decision* }
+
+define i32 @main() {
+entry:
+ br label %blah.i
+
+blah.i: ; preds = %cond_true.i, %entry
+ %tmp3.i = icmp eq %struct.decision* null, null ; <i1> [#uses=1]
+ br i1 %tmp3.i, label %clear_modes.exit, label %cond_true.i
+
+cond_true.i: ; preds = %blah.i
+ %tmp1.i = getelementptr %struct.decision* null, i32 0, i32 0 ; <i8*> [#uses=1]
+ store i8 0, i8* %tmp1.i
+ br label %blah.i
+
+clear_modes.exit: ; preds = %blah.i
+ call void @exit( i32 0 )
+ unreachable
+}
+
+define i32 @f(i8* %ptr) {
+entry:
+ br label %loop.head
+
+loop.head: ; preds = %cond.true, %entry
+ %x = phi i8* [ %ptr, %entry ], [ %ptr.i, %cond.true ] ; <i8*> [#uses=1]
+ %tmp3.i = icmp ne i8* %ptr, %x ; <i1> [#uses=1]
+ br i1 %tmp3.i, label %cond.true, label %exit
+
+cond.true: ; preds = %loop.head
+ %ptr.i = getelementptr i8* %ptr, i32 0 ; <i8*> [#uses=2]
+ store i8 0, i8* %ptr.i
+ br label %loop.head
+
+exit: ; preds = %loop.head
+ ret i32 0
+}
+
+define i32 @f2(i8* %p, i8* %q) {
+entry:
+ br label %loop.head
+
+loop.head: ; preds = %cond.true, %entry
+ %tmp3.i = icmp eq i8* null, %q ; <i1> [#uses=1]
+ br i1 %tmp3.i, label %exit, label %cond.true
+
+cond.true: ; preds = %loop.head
+ %ptr.i = getelementptr i8* %p, i32 0 ; <i8*> [#uses=2]
+ store i8 0, i8* %ptr.i
+ br label %loop.head
+
+exit: ; preds = %loop.head
+ ret i32 0
+}
+
+declare void @exit(i32)
diff --git a/test/Transforms/LICM/2007-09-24-PromoteNullValue.ll b/test/Transforms/LICM/2007-09-24-PromoteNullValue.ll
new file mode 100644
index 000000000000..f9f45f389b8a
--- /dev/null
+++ b/test/Transforms/LICM/2007-09-24-PromoteNullValue.ll
@@ -0,0 +1,46 @@
+; Do not promote null value because it may be unsafe to do so.
+; RUN: llvm-as < %s | opt -licm | llvm-dis | not grep promoted
+
+define i32 @f(i32 %foo, i32 %bar, i32 %com) {
+entry:
+ %tmp2 = icmp eq i32 %foo, 0 ; <i1> [#uses=1]
+ br i1 %tmp2, label %cond_next, label %cond_true
+
+cond_true: ; preds = %entry
+ br label %return
+
+cond_next: ; preds = %entry
+ br label %bb
+
+bb: ; preds = %bb15, %cond_next
+ switch i32 %bar, label %bb15 [
+ i32 1, label %bb6
+ ]
+
+bb6: ; preds = %bb
+ %tmp8 = icmp eq i32 %com, 0 ; <i1> [#uses=1]
+ br i1 %tmp8, label %cond_next14, label %cond_true11
+
+cond_true11: ; preds = %bb6
+ br label %return
+
+cond_next14: ; preds = %bb6
+ store i8 0, i8* null
+ br label %bb15
+
+bb15: ; preds = %cond_next14, %bb
+ br label %bb
+
+return: ; preds = %cond_true11, %cond_true
+ %storemerge = phi i32 [ 0, %cond_true ], [ undef, %cond_true11 ] ; <i32> [#uses=1]
+ ret i32 %storemerge
+}
+
+define i32 @kdMain() {
+entry:
+ %tmp1 = call i32 @f( i32 0, i32 1, i32 1 ) ; <i32> [#uses=0]
+ call void @exit( i32 0 )
+ unreachable
+}
+
+declare void @exit(i32)
diff --git a/test/Transforms/LICM/2007-10-01-PromoteSafeValue.ll b/test/Transforms/LICM/2007-10-01-PromoteSafeValue.ll
new file mode 100644
index 000000000000..7359cc0695ad
--- /dev/null
+++ b/test/Transforms/LICM/2007-10-01-PromoteSafeValue.ll
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | opt -licm | llvm-dis | grep promoted
+; Promote value if at least one use is safe
+
+
+define i32 @f2(i32* %p, i8* %q) {
+entry:
+ br label %loop.head
+
+loop.head: ; preds = %cond.true, %entry
+ store i32 20, i32* %p
+ %tmp3.i = icmp eq i8* null, %q ; <i1> [#uses=1]
+ br i1 %tmp3.i, label %exit, label %cond.true
+
+cond.true: ; preds = %loop.head
+ store i32 40, i32* %p
+ br label %loop.head
+
+exit: ; preds = %loop.head
+ ret i32 0
+}
+
diff --git a/test/Transforms/LICM/2008-05-20-AliasSetVAArg.ll b/test/Transforms/LICM/2008-05-20-AliasSetVAArg.ll
new file mode 100644
index 000000000000..dcb20e7bbd0c
--- /dev/null
+++ b/test/Transforms/LICM/2008-05-20-AliasSetVAArg.ll
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | opt -licm -disable-output
+; PR2346
+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 = "i686-pc-linux-gnu"
+ %struct._zval_struct = type { %union._double, i32, i8, i8, i8, i8 }
+ %union._double = type { double }
+
+define i8* @zend_fetch_resource(%struct._zval_struct** %passed_id, i32 %default_id, i8* %resource_type_name, i32* %found_resource_type, i32 %num_resource_types, ...) {
+entry:
+ br label %whilebody.i.i
+
+whilebody.i.i: ; preds = %whilebody.i.i, %entry
+ br i1 false, label %ifthen.i.i, label %whilebody.i.i
+
+ifthen.i.i: ; preds = %whilebody.i.i
+ br label %forcond
+
+forcond: ; preds = %forbody, %ifthen.i.i
+ br i1 false, label %forbody, label %afterfor
+
+forbody: ; preds = %forcond
+ va_arg i8** null, i32 ; <i32>:0 [#uses=0]
+ br i1 false, label %ifthen59, label %forcond
+
+ifthen59: ; preds = %forbody
+ unreachable
+
+afterfor: ; preds = %forcond
+ ret i8* null
+}
diff --git a/test/Transforms/LICM/2008-07-22-LoadGlobalConstant.ll b/test/Transforms/LICM/2008-07-22-LoadGlobalConstant.ll
new file mode 100644
index 000000000000..3824d5359772
--- /dev/null
+++ b/test/Transforms/LICM/2008-07-22-LoadGlobalConstant.ll
@@ -0,0 +1,23 @@
+; RUN: llvm-as < %s | opt -licm -enable-licm-constant-variables | llvm-dis | grep -A 1 entry | grep load.*@a
+@a = external constant float*
+
+define void @test(i32 %count) {
+entry:
+ br label %forcond
+
+forcond:
+ %i.0 = phi i32 [ 0, %entry ], [ %inc, %forbody ]
+ %cmp = icmp ult i32 %i.0, %count
+ br i1 %cmp, label %forbody, label %afterfor
+
+forbody:
+ %tmp3 = load float** @a
+ %arrayidx = getelementptr float* %tmp3, i32 %i.0
+ %tmp7 = uitofp i32 %i.0 to float
+ store float %tmp7, float* %arrayidx
+ %inc = add i32 %i.0, 1
+ br label %forcond
+
+afterfor:
+ ret void
+}
diff --git a/test/Transforms/LICM/2009-03-25-AliasSetTracker.ll b/test/Transforms/LICM/2009-03-25-AliasSetTracker.ll
new file mode 100644
index 000000000000..c3c9a810c52c
--- /dev/null
+++ b/test/Transforms/LICM/2009-03-25-AliasSetTracker.ll
@@ -0,0 +1,39 @@
+
+; RUN: llvm-as < %s | opt -licm -loop-index-split -instcombine -disable-output
+
+ %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i32, i32, [40 x i8] }
+ %struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, i32 }
+@"\01LC81" = external constant [4 x i8] ; <[4 x i8]*> [#uses=1]
+
+define fastcc void @hex_dump_internal(i8* %avcl, %struct.FILE* %f, i32 %level, i8* nocapture %buf, i32 %size) nounwind {
+entry:
+ br i1 false, label %bb4, label %return
+
+bb4: ; preds = %bb30, %entry
+ br label %bb6
+
+bb6: ; preds = %bb15, %bb4
+ %j.0.reg2mem.0 = phi i32 [ %2, %bb15 ], [ 0, %bb4 ] ; <i32> [#uses=2]
+ %0 = icmp slt i32 %j.0.reg2mem.0, 0 ; <i1> [#uses=1]
+ br i1 %0, label %bb7, label %bb13
+
+bb7: ; preds = %bb6
+ br label %bb15
+
+bb13: ; preds = %bb6
+ %1 = tail call i32 @fwrite(i8* getelementptr ([4 x i8]* @"\01LC81", i32 0, i32 0), i32 1, i32 3, i8* null) nounwind ; <i32> [#uses=0]
+ br label %bb15
+
+bb15: ; preds = %bb13, %bb7
+ %2 = add i32 %j.0.reg2mem.0, 1 ; <i32> [#uses=2]
+ %3 = icmp sgt i32 %2, 15 ; <i1> [#uses=1]
+ br i1 %3, label %bb30, label %bb6
+
+bb30: ; preds = %bb15
+ br i1 false, label %bb4, label %return
+
+return: ; preds = %bb30, %entry
+ ret void
+}
+
+declare i32 @fwrite(i8* nocapture, i32, i32, i8* nocapture) nounwind
diff --git a/test/Transforms/LICM/Preserve-LCSSA.ll b/test/Transforms/LICM/Preserve-LCSSA.ll
new file mode 100644
index 000000000000..850d071810ef
--- /dev/null
+++ b/test/Transforms/LICM/Preserve-LCSSA.ll
@@ -0,0 +1,25 @@
+; RUN: llvm-as < %s | opt -loop-rotate -licm -loop-unswitch -disable-output
+
+define i32 @stringSearch_Clib(i32 %count) {
+entry:
+ br i1 false, label %bb36, label %bb44
+
+bb4: ; preds = %bb36
+ br i1 false, label %cond_next, label %cond_true
+
+cond_true: ; preds = %bb4
+ ret i32 0
+
+cond_next: ; preds = %bb4
+ ret i32 0
+
+bb36: ; preds = %bb41, %entry
+ br i1 false, label %bb4, label %bb41
+
+bb41: ; preds = %bb36
+ %ttmp2 = icmp slt i32 0, %count ; <i1> [#uses=1]
+ br i1 %ttmp2, label %bb36, label %bb44
+
+bb44: ; preds = %bb41, %entry
+ ret i32 0
+}
diff --git a/test/Transforms/LICM/basictest.ll b/test/Transforms/LICM/basictest.ll
new file mode 100644
index 000000000000..0a57ce4539fe
--- /dev/null
+++ b/test/Transforms/LICM/basictest.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | opt -licm | llvm-dis
+
+define void @testfunc(i32 %i) {
+; <label>:0
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %j = phi i32 [ 0, %0 ], [ %Next, %Loop ] ; <i32> [#uses=1]
+ %i2 = mul i32 %i, 17 ; <i32> [#uses=1]
+ %Next = add i32 %j, %i2 ; <i32> [#uses=2]
+ %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]
+ br i1 %cond, label %Out, label %Loop
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LICM/call_sink_const_function.ll b/test/Transforms/LICM/call_sink_const_function.ll
new file mode 100644
index 000000000000..f187e27335ba
--- /dev/null
+++ b/test/Transforms/LICM/call_sink_const_function.ll
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | opt -basicaa -licm | llvm-dis | %prcontext sin 1 | grep Out:
+
+declare double @sin(double) readnone
+
+declare void @foo()
+
+define double @test(double %X) {
+ br label %Loop
+
+Loop: ; preds = %Loop, %0
+ call void @foo( )
+ %A = call double @sin( double %X ) readnone ; <double> [#uses=1]
+ br i1 true, label %Loop, label %Out
+
+Out: ; preds = %Loop
+ ret double %A
+}
diff --git a/test/Transforms/LICM/call_sink_pure_function.ll b/test/Transforms/LICM/call_sink_pure_function.ll
new file mode 100644
index 000000000000..c0457a17fc4e
--- /dev/null
+++ b/test/Transforms/LICM/call_sink_pure_function.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -basicaa -licm | llvm-dis | %prcontext strlen 1 | grep Out:
+
+declare i32 @strlen(i8*) readonly
+
+declare void @foo()
+
+define i32 @test(i8* %P) {
+ br label %Loop
+
+Loop: ; preds = %Loop, %0
+ %A = call i32 @strlen( i8* %P ) readonly ; <i32> [#uses=1]
+ br i1 false, label %Loop, label %Out
+
+Out: ; preds = %Loop
+ ret i32 %A
+}
diff --git a/test/Transforms/LICM/dg.exp b/test/Transforms/LICM/dg.exp
new file mode 100644
index 000000000000..f2005891a59a
--- /dev/null
+++ b/test/Transforms/LICM/dg.exp
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
diff --git a/test/Transforms/LICM/no-preheader-test.ll b/test/Transforms/LICM/no-preheader-test.ll
new file mode 100644
index 000000000000..6ea08612ea86
--- /dev/null
+++ b/test/Transforms/LICM/no-preheader-test.ll
@@ -0,0 +1,20 @@
+; Test that LICM works when there is not a loop-preheader
+; RUN: llvm-as < %s | opt -licm | llvm-dis
+
+define void @testfunc(i32 %i.s, i1 %ifcond) {
+ br i1 %ifcond, label %Then, label %Else
+Then: ; preds = %0
+ br label %Loop
+Else: ; preds = %0
+ br label %Loop
+Loop: ; preds = %Loop, %Else, %Then
+ %j = phi i32 [ 0, %Then ], [ 12, %Else ], [ %Next, %Loop ] ; <i32> [#uses=1]
+ %i = bitcast i32 %i.s to i32 ; <i32> [#uses=1]
+ %i2 = mul i32 %i, 17 ; <i32> [#uses=1]
+ %Next = add i32 %j, %i2 ; <i32> [#uses=2]
+ %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]
+ br i1 %cond, label %Out, label %Loop
+Out: ; preds = %Loop
+ ret void
+}
+
diff --git a/test/Transforms/LICM/scalar_promote.ll b/test/Transforms/LICM/scalar_promote.ll
new file mode 100644
index 000000000000..f6c0f0821a30
--- /dev/null
+++ b/test/Transforms/LICM/scalar_promote.ll
@@ -0,0 +1,35 @@
+; RUN: llvm-as < %s | opt -licm -disable-output -stats |& \
+; RUN: grep {memory locations promoted to register}
+@X = global i32 7 ; <i32*> [#uses=4]
+
+define void @testfunc(i32 %i) {
+; <label>:0
+ br label %Loop
+
+Loop: ; preds = %Loop, %0
+ %j = phi i32 [ 0, %0 ], [ %Next, %Loop ] ; <i32> [#uses=1]
+ %x = load i32* @X ; <i32> [#uses=1]
+ %x2 = add i32 %x, 1 ; <i32> [#uses=1]
+ store i32 %x2, i32* @X
+ %Next = add i32 %j, 1 ; <i32> [#uses=2]
+ %cond = icmp eq i32 %Next, 0 ; <i1> [#uses=1]
+ br i1 %cond, label %Out, label %Loop
+
+Out: ; preds = %Loop
+ ret void
+}
+
+define void @testhard(i32 %i) {
+ br label %Loop
+
+Loop: ; preds = %Loop, %0
+ %X1 = getelementptr i32* @X, i64 0 ; <i32*> [#uses=1]
+ %A = load i32* %X1 ; <i32> [#uses=1]
+ %V = add i32 %A, 1 ; <i32> [#uses=1]
+ %X2 = getelementptr i32* @X, i64 0 ; <i32*> [#uses=1]
+ store i32 %V, i32* %X2
+ br i1 false, label %Loop, label %Exit
+
+Exit: ; preds = %Loop
+ ret void
+}
diff --git a/test/Transforms/LICM/sink_critical_edge.ll b/test/Transforms/LICM/sink_critical_edge.ll
new file mode 100644
index 000000000000..6998ab1580c3
--- /dev/null
+++ b/test/Transforms/LICM/sink_critical_edge.ll
@@ -0,0 +1,16 @@
+; This testcase checks to make sure the sinker does not cause problems with
+; critical edges.
+
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext add 1 | grep Exit
+
+define void @test() {
+Entry:
+ br i1 false, label %Loop, label %Exit
+Loop: ; preds = %Loop, %Entry
+ %X = add i32 0, 1 ; <i32> [#uses=1]
+ br i1 false, label %Loop, label %Exit
+Exit: ; preds = %Loop, %Entry
+ %Y = phi i32 [ 0, %Entry ], [ %X, %Loop ] ; <i32> [#uses=0]
+ ret void
+}
+
diff --git a/test/Transforms/LICM/sink_inst.ll b/test/Transforms/LICM/sink_inst.ll
new file mode 100644
index 000000000000..e634c753f361
--- /dev/null
+++ b/test/Transforms/LICM/sink_inst.ll
@@ -0,0 +1,20 @@
+; If the result of an instruction is only used outside of the loop, sink
+; the instruction to the exit blocks instead of executing it on every
+; iteration of the loop.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext mul 1 | grep Out:
+
+define i32 @test(i32 %N) {
+Entry:
+ br label %Loop
+Loop: ; preds = %Loop, %Entry
+ %N_addr.0.pn = phi i32 [ %dec, %Loop ], [ %N, %Entry ] ; <i32> [#uses=3]
+ %tmp.6 = mul i32 %N, %N_addr.0.pn ; <i32> [#uses=1]
+ %tmp.7 = sub i32 %tmp.6, %N ; <i32> [#uses=1]
+ %dec = add i32 %N_addr.0.pn, -1 ; <i32> [#uses=1]
+ %tmp.1 = icmp ne i32 %N_addr.0.pn, 1 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret i32 %tmp.7
+}
+
diff --git a/test/Transforms/LICM/sink_load.ll b/test/Transforms/LICM/sink_load.ll
new file mode 100644
index 000000000000..87334840e054
--- /dev/null
+++ b/test/Transforms/LICM/sink_load.ll
@@ -0,0 +1,21 @@
+; To reduce register pressure, if a load is hoistable out of the loop, and the
+; result of the load is only used outside of the loop, sink the load instead of
+; hoisting it!
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext load 1 | grep Out:
+
+@X = global i32 5 ; <i32*> [#uses=1]
+
+define i32 @test(i32 %N) {
+Entry:
+ br label %Loop
+Loop: ; preds = %Loop, %Entry
+ %N_addr.0.pn = phi i32 [ %dec, %Loop ], [ %N, %Entry ] ; <i32> [#uses=2]
+ %tmp.6 = load i32* @X ; <i32> [#uses=1]
+ %dec = add i32 %N_addr.0.pn, -1 ; <i32> [#uses=1]
+ %tmp.1 = icmp ne i32 %N_addr.0.pn, 1 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret i32 %tmp.6
+}
+
diff --git a/test/Transforms/LICM/sink_multiple.ll b/test/Transforms/LICM/sink_multiple.ll
new file mode 100644
index 000000000000..c9341704738f
--- /dev/null
+++ b/test/Transforms/LICM/sink_multiple.ll
@@ -0,0 +1,21 @@
+; The loop sinker was running from the bottom of the loop to the top, causing
+; it to miss opportunities to sink instructions that depended on sinking other
+; instructions from the loop. Instead they got hoisted, which is better than
+; leaving them in the loop, but increases register pressure pointlessly.
+
+; RUN: llvm-as < %s | opt -licm | llvm-dis | \
+; RUN: %prcontext getelementptr 1 | grep Out:
+
+ %Ty = type { i32, i32 }
+@X = external global %Ty ; <%Ty*> [#uses=1]
+
+define i32 @test() {
+ br label %Loop
+Loop: ; preds = %Loop, %0
+ %dead = getelementptr %Ty* @X, i64 0, i32 0 ; <i32*> [#uses=1]
+ %sunk2 = load i32* %dead ; <i32> [#uses=1]
+ br i1 false, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret i32 %sunk2
+}
+
diff --git a/test/Transforms/LICM/sink_multiple_exits.ll b/test/Transforms/LICM/sink_multiple_exits.ll
new file mode 100644
index 000000000000..2882fa4b0af7
--- /dev/null
+++ b/test/Transforms/LICM/sink_multiple_exits.ll
@@ -0,0 +1,24 @@
+; This testcase ensures that we can sink instructions from loops with
+; multiple exits.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | \
+; RUN: %prcontext mul 1 | grep {Out\[12\]:}
+
+define i32 @test(i32 %N, i1 %C) {
+Entry:
+ br label %Loop
+Loop: ; preds = %ContLoop, %Entry
+ %N_addr.0.pn = phi i32 [ %dec, %ContLoop ], [ %N, %Entry ] ; <i32> [#uses=3]
+ %tmp.6 = mul i32 %N, %N_addr.0.pn ; <i32> [#uses=1]
+ %tmp.7 = sub i32 %tmp.6, %N ; <i32> [#uses=2]
+ %dec = add i32 %N_addr.0.pn, -1 ; <i32> [#uses=1]
+ br i1 %C, label %ContLoop, label %Out1
+ContLoop: ; preds = %Loop
+ %tmp.1 = icmp ne i32 %N_addr.0.pn, 1 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %Loop, label %Out2
+Out1: ; preds = %Loop
+ ret i32 %tmp.7
+Out2: ; preds = %ContLoop
+ ret i32 %tmp.7
+}
+
diff --git a/test/Transforms/LICM/sink_only_some_exits.ll b/test/Transforms/LICM/sink_only_some_exits.ll
new file mode 100644
index 000000000000..42cfece56c91
--- /dev/null
+++ b/test/Transforms/LICM/sink_only_some_exits.ll
@@ -0,0 +1,23 @@
+; This testcase checks to make sure we can sink values which are only live on
+; some exits out of the loop, and that we can do so without breaking dominator
+; info.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | \
+; RUN: %prcontext add 1 | grep exit2:
+
+define i32 @test(i1 %C1, i1 %C2, i32* %P, i32* %Q) {
+Entry:
+ br label %Loop
+Loop: ; preds = %Cont, %Entry
+ br i1 %C1, label %Cont, label %exit1
+Cont: ; preds = %Loop
+ %X = load i32* %P ; <i32> [#uses=2]
+ store i32 %X, i32* %Q
+ %V = add i32 %X, 1 ; <i32> [#uses=1]
+ br i1 %C2, label %Loop, label %exit2
+exit1: ; preds = %Loop
+ ret i32 0
+exit2: ; preds = %Cont
+ ret i32 %V
+}
+
diff --git a/test/Transforms/LICM/sink_phi_node_use.ll b/test/Transforms/LICM/sink_phi_node_use.ll
new file mode 100644
index 000000000000..6e558bb1e497
--- /dev/null
+++ b/test/Transforms/LICM/sink_phi_node_use.ll
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext add 1 | grep preheader.loopexit:
+
+define void @test() {
+loopentry.2.i:
+ br i1 false, label %no_exit.1.i.preheader, label %loopentry.3.i.preheader
+no_exit.1.i.preheader: ; preds = %loopentry.2.i
+ br label %no_exit.1.i
+no_exit.1.i: ; preds = %endif.8.i, %no_exit.1.i.preheader
+ br i1 false, label %return.i, label %endif.8.i
+endif.8.i: ; preds = %no_exit.1.i
+ %inc.1.i = add i32 0, 1 ; <i32> [#uses=1]
+ br i1 false, label %no_exit.1.i, label %loopentry.3.i.preheader.loopexit
+loopentry.3.i.preheader.loopexit: ; preds = %endif.8.i
+ br label %loopentry.3.i.preheader
+loopentry.3.i.preheader: ; preds = %loopentry.3.i.preheader.loopexit, %loopentry.2.i
+ %arg_num.0.i.ph13000 = phi i32 [ 0, %loopentry.2.i ], [ %inc.1.i, %loopentry.3.i.preheader.loopexit ] ; <i32> [#uses=0]
+ ret void
+return.i: ; preds = %no_exit.1.i
+ ret void
+}
+
diff --git a/test/Transforms/LICM/sink_trapping_inst.ll b/test/Transforms/LICM/sink_trapping_inst.ll
new file mode 100644
index 000000000000..8e79039efe4b
--- /dev/null
+++ b/test/Transforms/LICM/sink_trapping_inst.ll
@@ -0,0 +1,18 @@
+; Potentially trapping instructions may be sunk as long as they are guaranteed
+; to be executed.
+;
+; RUN: llvm-as < %s | opt -licm | llvm-dis | %prcontext div 1 | grep Out:
+
+define i32 @test(i32 %N) {
+Entry:
+ br label %Loop
+Loop: ; preds = %Loop, %Entry
+ %N_addr.0.pn = phi i32 [ %dec, %Loop ], [ %N, %Entry ] ; <i32> [#uses=3]
+ %tmp.6 = sdiv i32 %N, %N_addr.0.pn ; <i32> [#uses=1]
+ %dec = add i32 %N_addr.0.pn, -1 ; <i32> [#uses=1]
+ %tmp.1 = icmp ne i32 %N_addr.0.pn, 0 ; <i1> [#uses=1]
+ br i1 %tmp.1, label %Loop, label %Out
+Out: ; preds = %Loop
+ ret i32 %tmp.6
+}
+