188 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
 | 
						|
 | 
						|
 | 
						|
@gvar = external global i32
 | 
						|
 | 
						|
; dupbb has two predecessors, p1 and p2. p1 is hot, p2 is cold. So dupbb
 | 
						|
; should be placed after p1, and not duplicated into p2.
 | 
						|
;
 | 
						|
; CHECK-LABEL: test1
 | 
						|
; CHECK:       %p1
 | 
						|
; CHECK:       .LBB0_4: # %dupbb
 | 
						|
; CHECK:       %p2
 | 
						|
; CHECK:       jmp .LBB0_4
 | 
						|
 | 
						|
define void @test1(i32* %p) !prof !1 {
 | 
						|
entry:
 | 
						|
  br label %header
 | 
						|
 | 
						|
header:
 | 
						|
  %call = call zeroext i1 @a()
 | 
						|
  br i1 %call, label %p1, label %p2, !prof !2
 | 
						|
 | 
						|
p1:
 | 
						|
  call void @b()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p2:
 | 
						|
  call void @c()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
dupbb:
 | 
						|
  %cond = icmp eq i32* @gvar, %p
 | 
						|
  br i1 %cond, label %header, label %latch, !prof !3
 | 
						|
 | 
						|
latch:
 | 
						|
  %call3 = call zeroext i1 @a()
 | 
						|
  br i1 %call3, label %header, label %end, !prof !2
 | 
						|
 | 
						|
end:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
; dupbb has four predecessors p1, p2, p3 and p4. p1 and p2 are hot, p3 and  p4
 | 
						|
; are cold. So dupbb should be placed after p1, duplicated into p2. p3 and p4
 | 
						|
; should jump to dupbb.
 | 
						|
;
 | 
						|
; CHECK-LABEL: test2
 | 
						|
; CHECK:       %p1
 | 
						|
; CHECK:       .LBB1_8: # %dupbb
 | 
						|
;
 | 
						|
; CHECK:       %p2
 | 
						|
; CHECK:       callq c
 | 
						|
; CHECK-NEXT:  cmpq
 | 
						|
; CHECK-NEXT:  je
 | 
						|
; CHECK-NEXT:  jmp
 | 
						|
;
 | 
						|
; CHECK:       %p3
 | 
						|
; CHECK:       jmp .LBB1_8
 | 
						|
; CHECK:       %p4
 | 
						|
; CHECK:       jmp .LBB1_8
 | 
						|
 | 
						|
define void @test2(i32* %p) !prof !1 {
 | 
						|
entry:
 | 
						|
  br label %header
 | 
						|
 | 
						|
header:
 | 
						|
  %call = call zeroext i1 @a()
 | 
						|
  br i1 %call, label %bb1, label %bb2, !prof !2
 | 
						|
 | 
						|
bb1:
 | 
						|
  %call1 = call zeroext i1 @a()
 | 
						|
  br i1 %call1, label %p1, label %p2, !prof !4
 | 
						|
 | 
						|
bb2:
 | 
						|
  %call2 = call zeroext i1 @a()
 | 
						|
  br i1 %call2, label %p3, label %p4, !prof !4
 | 
						|
 | 
						|
p1:
 | 
						|
  call void @b()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p2:
 | 
						|
  call void @c()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p3:
 | 
						|
  call void @d()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p4:
 | 
						|
  call void @e()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
dupbb:
 | 
						|
  %cond = icmp eq i32* @gvar, %p
 | 
						|
  br i1 %cond, label %bb3, label %bb4, !prof !4
 | 
						|
 | 
						|
bb3:
 | 
						|
  call void @b()
 | 
						|
  br label %bb4
 | 
						|
 | 
						|
bb4:
 | 
						|
  %call4 = call zeroext i1 @a()
 | 
						|
  br i1 %call4, label %header, label %latch, !prof !3
 | 
						|
 | 
						|
latch:
 | 
						|
  %call3 = call zeroext i1 @a()
 | 
						|
  br i1 %call3, label %header, label %end, !prof !2
 | 
						|
 | 
						|
end:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
; dupbb has three predecessors p1, p2 and p3. p3 has two successors, so dupbb
 | 
						|
; can't be duplicated into p3, but it should not block it to be duplicated into
 | 
						|
; other predecessors.
 | 
						|
;
 | 
						|
; CHECK-LABEL: test3
 | 
						|
; CHECK:       %p1
 | 
						|
; CHECK:       .LBB2_6: # %dupbb
 | 
						|
;
 | 
						|
; CHECK:       %p2
 | 
						|
; CHECK:       callq c
 | 
						|
; CHECK:       cmpq
 | 
						|
; CHECK-NEXT:  je
 | 
						|
; CHECK-NEXT:  jmp
 | 
						|
;
 | 
						|
; CHECK:       %p3
 | 
						|
; CHECK:       jne .LBB2_6
 | 
						|
 | 
						|
define void @test3(i32* %p) !prof !1 {
 | 
						|
entry:
 | 
						|
  br label %header
 | 
						|
 | 
						|
header:
 | 
						|
  %call = call zeroext i1 @a()
 | 
						|
  br i1 %call, label %bb1, label %p3, !prof !2
 | 
						|
 | 
						|
bb1:
 | 
						|
  %call1 = call zeroext i1 @a()
 | 
						|
  br i1 %call1, label %p1, label %p2, !prof !4
 | 
						|
 | 
						|
p1:
 | 
						|
  call void @b()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p2:
 | 
						|
  call void @c()
 | 
						|
  br label %dupbb
 | 
						|
 | 
						|
p3:
 | 
						|
  %call2 = call zeroext i1 @a()
 | 
						|
  br i1 %call2, label %dupbb, label %bb4, !prof !4
 | 
						|
 | 
						|
dupbb:
 | 
						|
  %cond = icmp eq i32* @gvar, %p
 | 
						|
  br i1 %cond, label %bb3, label %bb4, !prof !4
 | 
						|
 | 
						|
bb3:
 | 
						|
  call void @b()
 | 
						|
  br label %bb4
 | 
						|
 | 
						|
bb4:
 | 
						|
  %call4 = call zeroext i1 @a()
 | 
						|
  br i1 %call4, label %header, label %latch, !prof !3
 | 
						|
 | 
						|
latch:
 | 
						|
  %call3 = call zeroext i1 @a()
 | 
						|
  br i1 %call3, label %header, label %end, !prof !2
 | 
						|
 | 
						|
end:
 | 
						|
  ret void
 | 
						|
}
 | 
						|
 | 
						|
declare zeroext i1 @a()
 | 
						|
declare void @b()
 | 
						|
declare void @c()
 | 
						|
declare void @d()
 | 
						|
declare void @e()
 | 
						|
declare void @f()
 | 
						|
 | 
						|
!1 = !{!"function_entry_count", i64 1000}
 | 
						|
!2 = !{!"branch_weights", i32 100, i32 1}
 | 
						|
!3 = !{!"branch_weights", i32 1, i32 100}
 | 
						|
!4 = !{!"branch_weights", i32 60, i32 40}
 |