[llvm-commits] [llvm] r80522 - in /llvm/trunk/test/Transforms/LICM: 2003-08-04-TrappingInstHoist.ll 2003-08-04-TrappingInstOkHoist.ll call_sink_const_function.ll call_sink_pure_function.ll sink_critical_edge.ll sink_inst.ll sink_load.ll sink_multiple.ll sink_multiple_exits.ll sink_only_some_exits.ll sink_phi_node_use.ll sink_trapping_inst.ll sinking.ll

Chris Lattner sabre at nondot.org
Sun Aug 30 15:13:26 PDT 2009


Author: lattner
Date: Sun Aug 30 17:13:26 2009
New Revision: 80522

URL: http://llvm.org/viewvc/llvm-project?rev=80522&view=rev
Log:
merge all sinking tests into one and convert them to filecheck.

Added:
    llvm/trunk/test/Transforms/LICM/sinking.ll
Removed:
    llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll
    llvm/trunk/test/Transforms/LICM/call_sink_const_function.ll
    llvm/trunk/test/Transforms/LICM/call_sink_pure_function.ll
    llvm/trunk/test/Transforms/LICM/sink_critical_edge.ll
    llvm/trunk/test/Transforms/LICM/sink_inst.ll
    llvm/trunk/test/Transforms/LICM/sink_load.ll
    llvm/trunk/test/Transforms/LICM/sink_multiple.ll
    llvm/trunk/test/Transforms/LICM/sink_multiple_exits.ll
    llvm/trunk/test/Transforms/LICM/sink_only_some_exits.ll
    llvm/trunk/test/Transforms/LICM/sink_phi_node_use.ll
    llvm/trunk/test/Transforms/LICM/sink_trapping_inst.ll
Modified:
    llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll

Modified: llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll?rev=80522&r1=80521&r2=80522&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll (original)
+++ llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstHoist.ll Sun Aug 30 17:13:26 2009
@@ -1,21 +1,25 @@
-; 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 
+; RUN: llvm-as < %s | opt -licm | llvm-dis | FileCheck %s
 
 @X = global i32 0		; <i32*> [#uses=1]
 
 declare void @foo()
 
-define i32 @test(i1 %c) {
+; This testcase tests for a problem where LICM hoists 
+; potentially trapping instructions when they are not guaranteed to execute.
+define i32 @test1(i1 %c) {
+; CHECK: @test1
 	%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
+; CHECK: IfUnEqual:
+; CHECK-NEXT: sdiv i32 4, %A
 	%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
@@ -24,3 +28,23 @@
 	ret i32 %C
 }
 
+
+declare void @foo2(i32)
+
+
+;; It is ok and desirable to hoist this potentially trapping instruction.
+define i32 @test2(i1 %c) {
+; CHECK: @test2
+; CHECK-NEXT: load i32* @X
+; CHECK-NEXT: %B = sdiv i32 4, %A
+	%A = load i32* @X		; <i32> [#uses=2]
+	br label %Loop
+Loop:
+        ;; Should have hoisted this div!
+	%B = sdiv i32 4, %A		; <i32> [#uses=2]
+	call void @foo2( i32 %B )
+	br i1 %c, label %Loop, label %Out
+Out:		; preds = %Loop
+	%C = sub i32 %A, %B		; <i32> [#uses=1]
+	ret i32 %C
+}

Removed: llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll (original)
+++ llvm/trunk/test/Transforms/LICM/2003-08-04-TrappingInstOkHoist.ll (removed)
@@ -1,21 +0,0 @@
-; 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
-
- at 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
-}

Removed: llvm/trunk/test/Transforms/LICM/call_sink_const_function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/call_sink_const_function.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/call_sink_const_function.ll (original)
+++ llvm/trunk/test/Transforms/LICM/call_sink_const_function.ll (removed)
@@ -1,17 +0,0 @@
-; 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
-}

Removed: llvm/trunk/test/Transforms/LICM/call_sink_pure_function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/call_sink_pure_function.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/call_sink_pure_function.ll (original)
+++ llvm/trunk/test/Transforms/LICM/call_sink_pure_function.ll (removed)
@@ -1,16 +0,0 @@
-; 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
-}

Removed: llvm/trunk/test/Transforms/LICM/sink_critical_edge.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_critical_edge.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_critical_edge.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_critical_edge.ll (removed)
@@ -1,16 +0,0 @@
-; 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_inst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_inst.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_inst.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_inst.ll (removed)
@@ -1,20 +0,0 @@
-; 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_load.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_load.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_load.ll (removed)
@@ -1,21 +0,0 @@
-; 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: 
-
- at 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_multiple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_multiple.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_multiple.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_multiple.ll (removed)
@@ -1,21 +0,0 @@
-; 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 }
- at 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_multiple_exits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_multiple_exits.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_multiple_exits.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_multiple_exits.ll (removed)
@@ -1,24 +0,0 @@
-; 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_only_some_exits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_only_some_exits.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_only_some_exits.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_only_some_exits.ll (removed)
@@ -1,23 +0,0 @@
-; 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_phi_node_use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_phi_node_use.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_phi_node_use.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_phi_node_use.ll (removed)
@@ -1,21 +0,0 @@
-; 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
-}
-

Removed: llvm/trunk/test/Transforms/LICM/sink_trapping_inst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sink_trapping_inst.ll?rev=80521&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sink_trapping_inst.ll (original)
+++ llvm/trunk/test/Transforms/LICM/sink_trapping_inst.ll (removed)
@@ -1,18 +0,0 @@
-; 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
-}
-

Added: llvm/trunk/test/Transforms/LICM/sinking.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/sinking.ll?rev=80522&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LICM/sinking.ll (added)
+++ llvm/trunk/test/Transforms/LICM/sinking.ll Sun Aug 30 17:13:26 2009
@@ -0,0 +1,235 @@
+; RUN: llvm-as < %s | opt -basicaa -licm | llvm-dis | FileCheck %s
+
+declare i32 @strlen(i8*) readonly
+
+declare void @foo()
+
+; Sink readonly function.
+define i32 @test1(i8* %P) {
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	%A = call i32 @strlen( i8* %P ) readonly
+	br i1 false, label %Loop, label %Out
+
+Out:		; preds = %Loop
+	ret i32 %A
+; CHECK: @test1
+; CHECK: Out:
+; CHECK-NEXT: call i32 @strlen
+; CHECK-NEXT: ret i32 %A
+}
+
+declare double @sin(double) readnone
+
+; Sink readnone function out of loop with unknown memory behavior.
+define double @test2(double %X) {
+	br label %Loop
+
+Loop:		; preds = %Loop, %0
+	call void @foo( )
+	%A = call double @sin( double %X ) readnone
+	br i1 true, label %Loop, label %Out
+
+Out:		; preds = %Loop
+	ret double %A
+; CHECK: @test2
+; CHECK: Out:
+; CHECK-NEXT: call double @sin
+; CHECK-NEXT: ret double %A
+}
+
+; This testcase checks to make sure the sinker does not cause problems with
+; critical edges.
+define void @test3() {
+Entry:
+	br i1 false, label %Loop, label %Exit
+Loop:
+	%X = add i32 0, 1
+	br i1 false, label %Loop, label %Exit
+Exit:
+	%Y = phi i32 [ 0, %Entry ], [ %X, %Loop ]
+	ret void
+        
+; CHECK: @test3
+; CHECK:     Exit.loopexit:
+; CHECK-NEXT:  %X = add i32 0, 1
+; CHECK-NEXT:  br label %Exit
+
+}
+
+; 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.
+;
+define i32 @test4(i32 %N) {
+Entry:
+	br label %Loop
+Loop:		; preds = %Loop, %Entry
+	%N_addr.0.pn = phi i32 [ %dec, %Loop ], [ %N, %Entry ]	
+	%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
+; CHECK: @test4
+; CHECK:     Out:
+; CHECK-NEXT:  mul i32 %N, %N_addr.0.pn
+; CHECK-NEXT:  sub i32 %tmp.6, %N
+; CHECK-NEXT:  ret i32
+}
+
+; 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!
+;
+ at X = global i32 5		; <i32*> [#uses=1]
+
+define i32 @test5(i32 %N) {
+Entry:
+	br label %Loop
+Loop:		; preds = %Loop, %Entry
+	%N_addr.0.pn = phi i32 [ %dec, %Loop ], [ %N, %Entry ]	
+	%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
+; CHECK: @test5
+; CHECK:     Out:
+; CHECK-NEXT:  %tmp.6 = load i32* @X
+; CHECK-NEXT:  ret i32 %tmp.6
+}
+
+
+
+; 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.
+
+	%Ty = type { i32, i32 }
+ at X2 = external global %Ty
+
+define i32 @test6() {
+	br label %Loop
+Loop:
+	%dead = getelementptr %Ty* @X2, i64 0, i32 0
+	%sunk2 = load i32* %dead
+	br i1 false, label %Loop, label %Out
+Out:		; preds = %Loop
+	ret i32 %sunk2
+; CHECK: @test6
+; CHECK:     Out:
+; CHECK-NEXT:  %dead = getelementptr %Ty* @X2, i64 0, i32 0
+; CHECK-NEXT:  %sunk2 = load i32* %dead
+; CHECK-NEXT:  ret i32 %sunk2
+}
+
+
+
+; This testcase ensures that we can sink instructions from loops with
+; multiple exits.
+;
+define i32 @test7(i32 %N, i1 %C) {
+Entry:
+	br label %Loop
+Loop:		; preds = %ContLoop, %Entry
+	%N_addr.0.pn = phi i32 [ %dec, %ContLoop ], [ %N, %Entry ]
+	%tmp.6 = mul i32 %N, %N_addr.0.pn
+	%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:
+	%tmp.1 = icmp ne i32 %N_addr.0.pn, 1
+	br i1 %tmp.1, label %Loop, label %Out2
+Out1:		; preds = %Loop
+	ret i32 %tmp.7
+Out2:		; preds = %ContLoop
+	ret i32 %tmp.7
+; CHECK: @test7
+; CHECK:     Out1:
+; CHECK-NEXT:  mul i32 %N, %N_addr.0.pn
+; CHECK-NEXT:  sub i32 %tmp.6, %N
+; CHECK-NEXT:  ret
+; CHECK:     Out2:
+; CHECK-NEXT:  mul i32 %N, %N_addr.0.pn
+; CHECK-NEXT:  sub i32 %tmp.6
+; CHECK-NEXT:  ret
+}
+
+
+; 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.
+define i32 @test8(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
+; CHECK: @test8
+; CHECK:     exit1:
+; CHECK-NEXT:  ret i32 0
+; CHECK:     exit2:
+; CHECK-NEXT:  %V = add i32 %X, 1
+; CHECK-NEXT:  ret i32 %V
+}
+
+
+define void @test9() {
+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
+
+; CHECK: @test9
+; CHECK: loopentry.3.i.preheader.loopexit:
+; CHECK-NEXT:  %inc.1.i = add i32 0, 1
+; CHECK-NEXT:  br label %loopentry.3.i.preheader
+}
+
+
+; Potentially trapping instructions may be sunk as long as they are guaranteed
+; to be executed.
+define i32 @test10(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
+        
+; CHECK: @test10
+; CHECK: Out: 
+; CHECK-NEXT:  %tmp.6 = sdiv i32 %N, %N_addr.0.pn
+; CHECK-NEXT:  ret i32 %tmp.6
+}
+





More information about the llvm-commits mailing list