Patch by David Conrad:
authorJim Grosbach <grosbach@apple.com>
Mon, 18 Jan 2010 19:58:49 +0000 (19:58 +0000)
committerJim Grosbach <grosbach@apple.com>
Mon, 18 Jan 2010 19:58:49 +0000 (19:58 +0000)
"On ARMv6T2 this turns cttz into rbit, clz instead of the 4 instruction
 sequence it is now."

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

lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td

index a260050cf363f501de829787c2e3b222b8a49032..073cbffa4bdc3ba9713ea27f12efe900d5a32c7e 100644 (file)
@@ -1680,6 +1680,12 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
     return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32,
                                   N->getOperand(0), getAL(CurDAG),
                                   CurDAG->getRegister(0, MVT::i32));
+  case ARMISD::RBIT: {
+    EVT VT = N->getValueType(0);
+    SDValue Ops[] = { N->getOperand(0),
+                      getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
+    return CurDAG->getMachineNode(ARM::RBIT, dl, VT, Ops, 3);
+  }
   case ISD::UMUL_LOHI: {
     if (Subtarget->isThumb1Only())
       break;
index 7b62c00e1dbd5c59f360927308783097bbd08f5f..73545298f9cb739c8e681da9de48956452bd3129 100644 (file)
@@ -340,7 +340,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
 
   // ARM does not have ROTL.
   setOperationAction(ISD::ROTL,  MVT::i32, Expand);
-  setOperationAction(ISD::CTTZ,  MVT::i32, Expand);
+  setOperationAction(ISD::CTTZ,  MVT::i32, Custom);
   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
   if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only())
     setOperationAction(ISD::CTLZ, MVT::i32, Expand);
@@ -482,6 +482,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
   case ARMISD::CMOV:          return "ARMISD::CMOV";
   case ARMISD::CNEG:          return "ARMISD::CNEG";
 
+  case ARMISD::RBIT:          return "ARMISD::RBIT";
+
   case ARMISD::FTOSI:         return "ARMISD::FTOSI";
   case ARMISD::FTOUI:         return "ARMISD::FTOUI";
   case ARMISD::SITOF:         return "ARMISD::SITOF";
@@ -2231,6 +2233,18 @@ SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) {
   return DAG.getMergeValues(Ops, 2, dl);
 }
 
+static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG,
+                         const ARMSubtarget *ST) {
+  EVT VT = N->getValueType(0);
+  DebugLoc dl = N->getDebugLoc();
+
+  if (!ST->hasV6T2Ops())
+    return SDValue();
+
+  SDValue rbit = DAG.getNode(ARMISD::RBIT, dl, VT, N->getOperand(0));
+  return DAG.getNode(ISD::CTLZ, dl, VT, rbit);
+}
+
 static SDValue LowerShift(SDNode *N, SelectionDAG &DAG,
                           const ARMSubtarget *ST) {
   EVT VT = N->getValueType(0);
@@ -3016,6 +3030,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
   case ISD::SHL_PARTS:     return LowerShiftLeftParts(Op, DAG);
   case ISD::SRL_PARTS:
   case ISD::SRA_PARTS:     return LowerShiftRightParts(Op, DAG);
+  case ISD::CTTZ:          return LowerCTTZ(Op.getNode(), DAG, Subtarget);
   case ISD::VSETCC:        return LowerVSETCC(Op, DAG);
   case ISD::BUILD_VECTOR:  return LowerBUILD_VECTOR(Op, DAG);
   case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
index e1b3348c2619fea62d3b9ad12f0541fc548424a1..cd9c027743a3645b652796bd685deb5a839f5d1e 100644 (file)
@@ -53,6 +53,8 @@ namespace llvm {
       CMOV,         // ARM conditional move instructions.
       CNEG,         // ARM conditional negate instructions.
 
+      RBIT,         // ARM bitreverse instruction
+
       FTOSI,        // FP to sint within a FP register.
       FTOUI,        // FP to uint within a FP register.
       SITOF,        // sint to FP within a FP register.
index f67e74a99ed656d4f190f9141cd906eba064035c..6ea56753f31600b59e883fe07432461b6034f0f5 100644 (file)
@@ -1455,6 +1455,13 @@ def CLZ  : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
   let Inst{19-16} = 0b1111;
 }
 
+def RBIT : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
+              "rbit", "\t$dst, $src", []>, Requires<[IsARM, HasV6T2]> {
+  let Inst{7-4}   = 0b0011;
+  let Inst{11-8}  = 0b1111;
+  let Inst{19-16} = 0b1111;
+}
+
 def REV  : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
               "rev", "\t$dst, $src",
               [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> {
index 769df7ed916005465335d3bf94e8bead02e0e65d..3670d0fefd769687a6026831f5a32ed0c67acd30 100644 (file)
@@ -1540,6 +1540,9 @@ class T2I_misc<bits<2> op1, bits<2> op2, dag oops, dag iops, InstrItinClass itin
 def t2CLZ : T2I_misc<0b11, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
                     "clz", "\t$dst, $src", [(set GPR:$dst, (ctlz GPR:$src))]>;
 
+def t2RBIT : T2I_misc<0b01, 0b10, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
+                      "rbit", "\t$dst, $src", []>;
+
 def t2REV : T2I_misc<0b01, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
                    "rev", ".w\t$dst, $src", [(set GPR:$dst, (bswap GPR:$src))]>;