forked from OSchip/llvm-project
merge all sinking tests into one and convert them to filecheck.
llvm-svn: 80522
This commit is contained in:
parent
362654f51c
commit
71d51a2d79
|
@ -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 @@ Out: ; preds = %LoopTail
|
|||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
@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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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:
|
||||
|
||||
@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
|
||||
}
|
||||
|
|
@ -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 }
|
||||
@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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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!
|
||||
;
|
||||
@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 }
|
||||
@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
|
||||
}
|
||||
|
Loading…
Reference in New Issue