; 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(ptr %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 ptr @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(ptr %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 ptr @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(ptr %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 ptr @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}