1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 13:11:39 +01:00
llvm-mirror/test/CodeGen/X86/cmov-into-branch.ll
Sanjay Patel 7177ce0576 [CodeGenPrepare] use branch weight metadata to decide if a select should be turned into a branch
This is part of solving PR27344:
https://llvm.org/bugs/show_bug.cgi?id=27344

CGP should undo the SimplifyCFG transform for the same reason that earlier patches have used this
same mechanism: it's possible that passes between SimplifyCFG and CGP may be able to optimize the
IR further with a select in place.

For the TLI hook default, >99% taken or not taken is chosen as the default threshold for a highly
predictable branch. Even the most limited HW branch predictors will be correct on this branch almost
all the time, so even a massive mispredict penalty perf loss would be overcome by the win from all
the times the branch was predicted correctly.

As a follow-up, we could make the default target hook less conservative by using the SchedMachineModel's
MispredictPenalty. Or we could just let targets override the default by implementing the hook with that
and other target-specific options. Note that trying to statically determine mispredict rates for 
close-to-balanced profile weight data is generally impossible if the HW is sufficiently advanced. Ie, 
50/50 taken/not-taken might still be 100% predictable.

Finally, note that this patch as-is will not solve PR27344 because the current __builtin_unpredictable()
branch weight default values are 4 and 64. A proposal to change that is in D19435.

Differential Revision: http://reviews.llvm.org/D19488

llvm-svn: 267572
2016-04-26 17:11:17 +00:00

122 lines
3.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
; cmp with single-use load, should not form branch.
define i32 @test1(double %a, double* nocapture %b, i32 %x, i32 %y) {
; CHECK-LABEL: test1:
; CHECK: # BB#0:
; CHECK-NEXT: ucomisd (%rdi), %xmm0
; CHECK-NEXT: cmovbel %edx, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
;
%load = load double, double* %b, align 8
%cmp = fcmp olt double %load, %a
%cond = select i1 %cmp, i32 %x, i32 %y
ret i32 %cond
}
; Sanity check: no load.
define i32 @test2(double %a, double %b, i32 %x, i32 %y) {
; CHECK-LABEL: test2:
; CHECK: # BB#0:
; CHECK-NEXT: ucomisd %xmm1, %xmm0
; CHECK-NEXT: cmovbel %esi, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
;
%cmp = fcmp ogt double %a, %b
%cond = select i1 %cmp, i32 %x, i32 %y
ret i32 %cond
}
; Multiple uses of the load.
define i32 @test4(i32 %a, i32* nocapture %b, i32 %x, i32 %y) {
; CHECK-LABEL: test4:
; CHECK: # BB#0:
; CHECK-NEXT: movl (%rsi), %eax
; CHECK-NEXT: cmpl %edi, %eax
; CHECK-NEXT: cmovael %ecx, %edx
; CHECK-NEXT: addl %edx, %eax
; CHECK-NEXT: retq
;
%load = load i32, i32* %b, align 4
%cmp = icmp ult i32 %load, %a
%cond = select i1 %cmp, i32 %x, i32 %y
%add = add i32 %cond, %load
ret i32 %add
}
; Multiple uses of the cmp.
define i32 @test5(i32 %a, i32* nocapture %b, i32 %x, i32 %y) {
; CHECK-LABEL: test5:
; CHECK: # BB#0:
; CHECK-NEXT: cmpl %edi, (%rsi)
; CHECK-NEXT: cmoval %edi, %ecx
; CHECK-NEXT: cmovael %edx, %ecx
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: retq
;
%load = load i32, i32* %b, align 4
%cmp = icmp ult i32 %load, %a
%cmp1 = icmp ugt i32 %load, %a
%cond = select i1 %cmp1, i32 %a, i32 %y
%cond5 = select i1 %cmp, i32 %cond, i32 %x
ret i32 %cond5
}
; If a select is not obviously predictable, don't turn it into a branch.
define i32 @weighted_select1(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select1:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
; CHECK-NEXT: cmovnel %edi, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !0
ret i32 %sel
}
; If a select is obviously predictable, turn it into a branch.
define i32 @weighted_select2(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select2:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
; CHECK-NEXT: jne [[LABEL_BB5:.*]]
; CHECK: movl %esi, %edi
; CHECK-NEXT: [[LABEL_BB5]]
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !1
ret i32 %sel
}
; Note the reversed profile weights: it doesn't matter if it's
; obviously true or obviously false.
; Either one should become a branch rather than conditional move.
; TODO: But likely true vs. likely false should affect basic block placement?
define i32 @weighted_select3(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select3:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
; CHECK-NEXT: jne [[LABEL_BB6:.*]]
; CHECK: movl %esi, %edi
; CHECK-NEXT: [[LABEL_BB6]]
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !2
ret i32 %sel
}
!0 = !{!"branch_weights", i32 1, i32 99}
!1 = !{!"branch_weights", i32 1, i32 100}
!2 = !{!"branch_weights", i32 100, i32 1}