Don't emit a bit test if there is only one case the test can yield false. A simple SETNE is sufficient.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135126 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2011-07-14 01:38:42 +00:00
parent d77ec6208c
commit 3ff25514ce
3 changed files with 33 additions and 10 deletions

View File

@ -1727,7 +1727,8 @@ void SelectionDAGBuilder::visitBitTestCase(BitTestBlock &BB,
SDValue ShiftOp = DAG.getCopyFromReg(getControlRoot(), getCurDebugLoc(),
Reg, VT);
SDValue Cmp;
if (CountPopulation_64(B.Mask) == 1) {
unsigned PopCount = CountPopulation_64(B.Mask);
if (PopCount == 1) {
// Testing for a single bit; just compare the shift count with what it
// would need to be to shift a 1 bit in that position.
Cmp = DAG.getSetCC(getCurDebugLoc(),
@ -1735,6 +1736,13 @@ void SelectionDAGBuilder::visitBitTestCase(BitTestBlock &BB,
ShiftOp,
DAG.getConstant(CountTrailingZeros_64(B.Mask), VT),
ISD::SETEQ);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
Cmp = DAG.getSetCC(getCurDebugLoc(),
TLI.getSetCCResultType(VT),
ShiftOp,
DAG.getConstant(CountTrailingOnes_64(B.Mask), VT),
ISD::SETNE);
} else {
// Make desired shift
SDValue SwitchVal = DAG.getNode(ISD::SHL, getCurDebugLoc(), VT,

View File

@ -1762,7 +1762,6 @@ case it choses instead to keep the max operation obvious.
//===---------------------------------------------------------------------===//
Switch lowering generates less than ideal code for the following switch:
define void @a(i32 %x) nounwind {
entry:
switch i32 %x, label %if.end [
@ -1783,19 +1782,15 @@ declare void @foo()
Generated code on x86-64 (other platforms give similar results):
a:
cmpl $5, %edi
ja .LBB0_2
movl %edi, %eax
movl $47, %ecx
btq %rax, %rcx
jb .LBB0_3
ja LBB2_2
cmpl $4, %edi
jne LBB2_3
.LBB0_2:
ret
.LBB0_3:
jmp foo # TAILCALL
The movl+movl+btq+jb could be simplified to a cmpl+jne.
Or, if we wanted to be really clever, we could simplify the whole thing to
If we wanted to be really clever, we could simplify the whole thing to
something like the following, which eliminates a branch:
xorl $1, %edi
cmpl $4, %edi

View File

@ -79,3 +79,23 @@ if.end: ; preds = %entry
}
declare void @bar()
define void @test3(i32 %x) nounwind {
; CHECK: test3:
; CHECK: cmpl $5
; CHECK: ja
; CHECK: cmpl $4
; CHECK: jne
switch i32 %x, label %if.end [
i32 0, label %if.then
i32 1, label %if.then
i32 2, label %if.then
i32 3, label %if.then
i32 5, label %if.then
]
if.then:
tail call void @bar() nounwind
ret void
if.end:
ret void
}