Use standard promotion for i8 CTTZ nodes and i8 CTLZ nodes when the
authorChandler Carruth <chandlerc@gmail.com>
Sat, 24 Dec 2011 12:12:34 +0000 (12:12 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sat, 24 Dec 2011 12:12:34 +0000 (12:12 +0000)
LZCNT instructions are available. Force promotion to i32 to get
a smaller encoding since the fix-ups necessary are just as complex for
either promoted type

We can't do standard promotion for CTLZ when lowering through BSR
because it results in poor code surrounding the 'xor' at the end of this
instruction. Essentially, if we promote the entire CTLZ node to i32, we
end up doing the xor on a 32-bit CTLZ implementation, and then
subtracting appropriately to get back to an i8 value. Instead, our
custom logic just uses the knowledge of the incoming size to compute
a perfect xor. I'd love to know of a way to fix this, but so far I'm
drawing a blank. I suspect the legalizer could be more clever and/or it
could collude with the DAG combiner, but how... ;]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147251 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/bmi.ll
test/CodeGen/X86/clz.ll
test/CodeGen/X86/lzcnt.ll

index 8aa62d25d7cc5dce66d7bf71db0c8fbdc0323f04..b1971c1c5a72327a3d145410a22455cf779f0af3 100644 (file)
@@ -379,25 +379,31 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
   setOperationAction(ISD::FREM             , MVT::f80  , Expand);
   setOperationAction(ISD::FLT_ROUNDS_      , MVT::i32  , Custom);
 
+  // Promote the i8 variants and force them on up to i32 which has a shorter
+  // encoding.
+  setOperationAction(ISD::CTTZ             , MVT::i8   , Promote);
+  AddPromotedToType (ISD::CTTZ             , MVT::i8   , MVT::i32);
+  setOperationAction(ISD::CTTZ_ZERO_UNDEF  , MVT::i8   , Promote);
+  AddPromotedToType (ISD::CTTZ_ZERO_UNDEF  , MVT::i8   , MVT::i32);
   if (Subtarget->hasBMI()) {
-    setOperationAction(ISD::CTTZ           , MVT::i8   , Promote);
-    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i8   , Expand);
     setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i16  , Expand);
     setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32  , Expand);
     if (Subtarget->is64Bit())
       setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
   } else {
-    setOperationAction(ISD::CTTZ           , MVT::i8   , Custom);
     setOperationAction(ISD::CTTZ           , MVT::i16  , Custom);
     setOperationAction(ISD::CTTZ           , MVT::i32  , Custom);
-    setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i8   , Promote);
     if (Subtarget->is64Bit())
       setOperationAction(ISD::CTTZ         , MVT::i64  , Custom);
   }
 
   if (Subtarget->hasLZCNT()) {
+    // When promoting the i8 variants, force them to i32 for a shorter
+    // encoding.
     setOperationAction(ISD::CTLZ           , MVT::i8   , Promote);
-    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8   , Expand);
+    AddPromotedToType (ISD::CTLZ           , MVT::i8   , MVT::i32);
+    setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8   , Promote);
+    AddPromotedToType (ISD::CTLZ_ZERO_UNDEF, MVT::i8   , MVT::i32);
     setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i16  , Expand);
     setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32  , Expand);
     if (Subtarget->is64Bit())
@@ -9876,32 +9882,22 @@ SDValue X86TargetLowering::LowerCTLZ_ZERO_UNDEF(SDValue Op,
 
 SDValue X86TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) const {
   EVT VT = Op.getValueType();
-  EVT OpVT = VT;
   unsigned NumBits = VT.getSizeInBits();
   DebugLoc dl = Op.getDebugLoc();
-
   Op = Op.getOperand(0);
-  if (VT == MVT::i8) {
-    OpVT = MVT::i32;
-    Op = DAG.getNode(ISD::ZERO_EXTEND, dl, OpVT, Op);
-  }
 
   // Issue a bsf (scan bits forward) which also sets EFLAGS.
-  SDVTList VTs = DAG.getVTList(OpVT, MVT::i32);
+  SDVTList VTs = DAG.getVTList(VT, MVT::i32);
   Op = DAG.getNode(X86ISD::BSF, dl, VTs, Op);
 
   // If src is zero (i.e. bsf sets ZF), returns NumBits.
   SDValue Ops[] = {
     Op,
-    DAG.getConstant(NumBits, OpVT),
+    DAG.getConstant(NumBits, VT),
     DAG.getConstant(X86::COND_E, MVT::i8),
     Op.getValue(1)
   };
-  Op = DAG.getNode(X86ISD::CMOV, dl, OpVT, Ops, array_lengthof(Ops));
-
-  if (VT == MVT::i8)
-    Op = DAG.getNode(ISD::TRUNCATE, dl, MVT::i8, Op);
-  return Op;
+  return DAG.getNode(X86ISD::CMOV, dl, VT, Ops, array_lengthof(Ops));
 }
 
 // Lower256IntArith - Break a 256-bit integer operation into two new 128-bit
index e79c92f1e2c14faaa4ea8e31b5b3f43a8884c599..43c47c0fa8a517cbb94358ba8f3df27434d407e4 100644 (file)
@@ -9,7 +9,7 @@ define i8 @t1(i8 %x) nounwind  {
   %tmp = tail call i8 @llvm.cttz.i8( i8 %x, i1 false )
   ret i8 %tmp
 ; CHECK: t1:
-; CHECK: tzcntw
+; CHECK: tzcntl
 }
 
 define i16 @t2(i16 %x) nounwind  {
@@ -37,7 +37,7 @@ define i8 @t5(i8 %x) nounwind  {
   %tmp = tail call i8 @llvm.cttz.i8( i8 %x, i1 true )
   ret i8 %tmp
 ; CHECK: t5:
-; CHECK: tzcntw
+; CHECK: tzcntl
 }
 
 define i16 @t6(i16 %x) nounwind  {
index 6f4d305385b6c63427d4a86d9e7b859ddbd7f97e..763079f3446f280e02a3425eb8d936d69ec10fab 100644 (file)
@@ -13,7 +13,7 @@ define i8 @cttz_i8(i8 %x)  {
   %tmp = call i8 @llvm.cttz.i8( i8 %x, i1 true )
   ret i8 %tmp
 ; CHECK: cttz_i8:
-; CHECK: bsfw
+; CHECK: bsfl
 ; CHECK-NOT: cmov
 ; CHECK: ret
 }
index eb010d7f5a8beba3a2d47144df032c8bad83b239..2faa24a9a54413715fcc5c52c4ccea1092898635 100644 (file)
@@ -9,7 +9,7 @@ define i8 @t1(i8 %x) nounwind  {
        %tmp = tail call i8 @llvm.ctlz.i8( i8 %x, i1 false )
        ret i8 %tmp
 ; CHECK: t1:
-; CHECK: lzcntw
+; CHECK: lzcntl
 }
 
 define i16 @t2(i16 %x) nounwind  {
@@ -37,7 +37,7 @@ define i8 @t5(i8 %x) nounwind  {
        %tmp = tail call i8 @llvm.ctlz.i8( i8 %x, i1 true )
        ret i8 %tmp
 ; CHECK: t5:
-; CHECK: lzcntw
+; CHECK: lzcntl
 }
 
 define i16 @t6(i16 %x) nounwind  {