Don't emit a bit test if there is only one case the test can yield false. A simple...
authorBenjamin Kramer <benny.kra@googlemail.com>
Thu, 14 Jul 2011 01:38:42 +0000 (01:38 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Thu, 14 Jul 2011 01:38:42 +0000 (01:38 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135126 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/Target/README.txt
test/CodeGen/X86/switch-bt.ll

index 66b6024ba291cb6c33d7491539753c5e4667cc80..3a04ee1e938b1b9ac036c4060e500c501e54e441 100644 (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,
index 4e382e8f8ec1aa49dbfe5150e98918857a0e3b7d..4cc95340890d4cf997d9a91192ef435e4aacb2d1 100644 (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
index 9f491d452fa80ace073bee91d7d01d9bc526f098..8e39342214357a1f0db34d34ea8c044b1af42105 100644 (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
+}