forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			250 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: opt < %s -basicaa -licm -S | 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
 | 
						|
}
 | 
						|
 | 
						|
; Should delete, not sink, dead instructions.
 | 
						|
define void @test11() {
 | 
						|
	br label %Loop
 | 
						|
Loop:
 | 
						|
	%dead = getelementptr %Ty* @X2, i64 0, i32 0
 | 
						|
	br i1 false, label %Loop, label %Out
 | 
						|
Out:
 | 
						|
	ret void
 | 
						|
; CHECK: @test11
 | 
						|
; CHECK:     Out:
 | 
						|
; CHECK-NEXT:  ret void
 | 
						|
}
 | 
						|
 | 
						|
 |