diff options
Diffstat (limited to 'test/Transforms/LICM')
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 +} + |