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}
 |