Implement count leading zeros (ctlz), count trailing zeros (cttz), and count
authorAndrew Lenharth <andrewl@lenharth.org>
Tue, 3 May 2005 17:19:30 +0000 (17:19 +0000)
committerAndrew Lenharth <andrewl@lenharth.org>
Tue, 3 May 2005 17:19:30 +0000 (17:19 +0000)
population (ctpop).  Generic lowering is implemented, however only promotion
is implemented for SelectionDAG at the moment.

More coming soon.

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

14 files changed:
include/llvm/CodeGen/SelectionDAG.h
include/llvm/CodeGen/SelectionDAGNodes.h
include/llvm/Intrinsics.h
lib/CodeGen/IntrinsicLowering.cpp
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/Alpha/AlphaISelPattern.cpp
lib/Target/Alpha/AlphaInstrInfo.td
lib/Target/PowerPC/PPC64ISelPattern.cpp
lib/Target/PowerPC/PPCISelPattern.cpp
lib/Target/X86/X86ISelPattern.cpp
lib/VMCore/Function.cpp
lib/VMCore/Verifier.cpp

index f3d41cea15f7e85f8de9acdbc6b6aff9dfe76e1d..a8b42e7155d56de4987805b7bbd7ac29b10dbcb4 100644 (file)
@@ -44,6 +44,10 @@ class SelectionDAG {
 
   // AllNodes - All of the nodes in the DAG
   std::vector<SDNode*> AllNodes;
+
+  // ValueNodes - track SrcValue nodes
+  std::map<std::pair<const Value*, int>, SDNode*> ValueNodes;
+
 public:
   SelectionDAG(TargetLowering &tli, MachineFunction &mf) : TLI(tli), MF(mf) {
     EntryNode = Root = getNode(ISD::EntryToken, MVT::Other);
@@ -183,7 +187,7 @@ public:
   SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, SDOperand SV);
 
   // getSrcValue - construct a node to track a Value* through the backend
-  SDOperand getSrcValue(const Value* I);
+  SDOperand getSrcValue(const Value* I, int offset = 0);
 
   void replaceAllUsesWith(SDOperand Old, SDOperand New) {
     assert(Old != New && "RAUW self!");
index f3be3344a9f1e094a800d7a90e423562cc2feab6..97584d736ae6e1d968731449775b0cd6b6c1f5c9 100644 (file)
@@ -100,6 +100,9 @@ namespace ISD {
     // Bitwise operators.
     AND, OR, XOR, SHL, SRA, SRL,
 
+    // Counting operators
+    CTTZ, CTLZ, CTPOP,
+
     // Select operator.
     SELECT,
 
@@ -546,7 +549,7 @@ protected:
       ND = N4.Val->getNodeDepth();
     NodeDepth = ND+1;
 
-    Operands.reserve(3); Operands.push_back(N1); Operands.push_back(N2);
+    Operands.reserve(4); Operands.push_back(N1); Operands.push_back(N2);
     Operands.push_back(N3); Operands.push_back(N4);
     N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this);
     N3.Val->Uses.push_back(this); N4.Val->Uses.push_back(this);
@@ -748,13 +751,15 @@ public:
 
 class SrcValueSDNode : public SDNode {
   const Value *V;
+  int offset;
 protected:
   friend class SelectionDAG;
-  SrcValueSDNode(const Value* v)
-    : SDNode(ISD::SRCVALUE, MVT::Other), V(v) {}
+  SrcValueSDNode(const Value* v, int o)
+    : SDNode(ISD::SRCVALUE, MVT::Other), V(v), offset(o) {}
 
 public:
   const Value *getValue() const { return V; }
+  int getOffset() const { return offset; }
 
   static bool classof(const SrcValueSDNode *) { return true; }
   static bool classof(const SDNode *N) {
index 7acd5ca71a33bfd448daa3e42583203f89c21920..bbf2da36ae4c2956628f9d5f5d527d1525a34547 100644 (file)
@@ -63,13 +63,17 @@ namespace Intrinsic {
 
     // libm related functions.
     isunordered,    // Return true if either argument is a NaN
-    sqrt,
+    ctpop, //count population
+    ctlz, //count leading zeros
+    cttz, //count trailing zeros
+    sqrt, //square root
 
     // Input/Output intrinsics.
     readport,
     writeport,
     readio,
     writeio
+
   };
 
 } // End Intrinsic namespace
index 36f413a14f793723a0ea315c86014dd1852a695c..0bad510324ecee27200372404665ab1250e9f87a 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/Instructions.h"
+#include "llvm/Type.h"
 #include <iostream>
 
 using namespace llvm;
@@ -164,6 +165,201 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
                     AbortFCache);
     break;
   }
+  case Intrinsic::ctpop: {
+    Value *Src = CI->getOperand(1);
+    switch (CI->getOperand(0)->getType()->getTypeID())
+    {
+    case Type::SByteTyID:
+    case Type::UByteTyID:
+      {
+        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
+        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 2);
+        MA = ConstantUInt::get(Type::UIntTy, 0x33);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And,
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 4);
+        MA = ConstantUInt::get(Type::UIntTy, 0x0F);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA), "ctpop");
+      }
+      break;
+    case Type::ShortTyID:
+    case Type::UShortTyID:
+      {
+        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
+        Value* MA = ConstantUInt::get(Type::UIntTy, 0x5555);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 2);
+        MA = ConstantUInt::get(Type::UIntTy, 0x3333);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 4);
+        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 8);
+        MA = ConstantUInt::get(Type::UIntTy, 0x00FF);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA), "ctpop");
+
+      }
+      break;
+    case Type::IntTyID:
+    case Type::UIntTyID:
+      {
+        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
+        Value* MA = ConstantUInt::get(Type::UIntTy, 0x55555555);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 2);
+        MA = ConstantUInt::get(Type::UIntTy, 0x33333333);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 4);
+        MA = ConstantUInt::get(Type::UIntTy, 0x0F0F0F0F);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 8);
+        MA = ConstantUInt::get(Type::UIntTy, 0x00FF00FF);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 8);
+        MA = ConstantUInt::get(Type::UIntTy, 0x0000FFFF);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA), "ctpop");
+      }
+      break;
+    case Type::LongTyID:
+    case Type::ULongTyID:
+      {
+        Value* SA = ConstantUInt::get(Type::UByteTy, 1);
+        Value* MA = ConstantUInt::get(Type::ULongTy, 0x5555555555555555ULL);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 2);
+        MA = ConstantUInt::get(Type::ULongTy, 0x3333333333333333ULL);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 4);
+        MA = ConstantUInt::get(Type::ULongTy, 0x0F0F0F0F0F0F0F0FULL);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 8);
+        MA = ConstantUInt::get(Type::ULongTy, 0x00FF00FF00FF00FFULL);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA));
+        SA = ConstantUInt::get(Type::UByteTy, 16);
+        MA = ConstantUInt::get(Type::ULongTy, 0x00000000FFFFFFFFULL);
+        Src = BinaryOperator::create(Instruction::Add,
+                BinaryOperator::create(Instruction::And, Src, MA),
+                BinaryOperator::create(Instruction::And, 
+                                       new ShiftInst(Instruction::Shr, Src, SA),
+                                       MA), "ctpop");
+      }
+      break;
+    default:
+      abort();
+    }
+        
+    CI->replaceAllUsesWith(Src);
+    break;
+  }
+  case Intrinsic::ctlz: {
+    Value *Src = CI->getOperand(1);
+    Value* SA;
+    switch (CI->getOperand(0)->getType()->getTypeID())
+    {
+    case Type::LongTyID:
+    case Type::ULongTyID:
+      SA = ConstantUInt::get(Type::UByteTy, 32);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+    case Type::IntTyID:
+    case Type::UIntTyID:
+      SA = ConstantUInt::get(Type::UByteTy, 16);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+    case Type::ShortTyID:
+    case Type::UShortTyID:
+      SA = ConstantUInt::get(Type::UByteTy, 8);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+    default:
+      SA = ConstantUInt::get(Type::UByteTy, 1);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+      SA = ConstantUInt::get(Type::UByteTy, 2);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+      SA = ConstantUInt::get(Type::UByteTy, 4);
+      Src = BinaryOperator::create(Instruction::Or, Src, new ShiftInst(Instruction::Shr, Src, SA));
+    };
+    Src = BinaryOperator::createNot(Src);
+
+    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
+                                    CI->getCalledFunction()->getLinkage(),
+                                    "llvm.ctpop"), Src);
+    CI->replaceAllUsesWith(Src);
+    break;
+  }
+  case Intrinsic::cttz: {
+    Value *Src = CI->getOperand(1);
+    Src = BinaryOperator::create(Instruction::And, BinaryOperator::createNot(Src),
+            BinaryOperator::create(Instruction::Sub, Src, 
+                            ConstantUInt::get(CI->getOperand(0)->getType(), 1)));
+    Src = new CallInst(new Function(CI->getCalledFunction()->getFunctionType(),
+                                    CI->getCalledFunction()->getLinkage(),
+                                    "llvm.ctpop"), Src);
+    CI->replaceAllUsesWith(Src);
+    break;
+  }
 
   case Intrinsic::returnaddress:
   case Intrinsic::frameaddress:
index 52570824c3a1050eb59463a959e0eb63f1a07552..adb88bf9b1874fb6fb3221cab59a7de6937671a6 100644 (file)
@@ -987,6 +987,51 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     }
     break;
 
+  case ISD::CTPOP:
+  case ISD::CTTZ:
+  case ISD::CTLZ:
+    Tmp1 = LegalizeOp(Node->getOperand(0));   // Op
+    switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+    case TargetLowering::Legal:
+      if (Tmp1 != Node->getOperand(0))
+        Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1);
+      break;
+    case TargetLowering::Promote: {
+      MVT::ValueType OVT = Tmp1.getValueType();
+      MVT::ValueType NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT);
+      //Zero extend the argument
+      Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, NVT, Tmp1);
+      // Perform the larger operation, then subtract if needed.
+      Tmp1 = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1);
+      switch(Node->getOpcode())
+      {
+      case ISD::CTPOP:
+        Result = Tmp1;
+        break;
+      case ISD::CTTZ:
+        //if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT)
+        Tmp2 = DAG.getSetCC(ISD::SETEQ, MVT::i1, Tmp1, 
+                            DAG.getConstant(getSizeInBits(NVT), NVT));
+        Result = DAG.getNode(ISD::SELECT, NVT, Tmp2, 
+                           DAG.getConstant(getSizeInBits(OVT),NVT), Tmp1);
+        break;
+      case ISD::CTLZ:
+        //Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
+        Result = DAG.getNode(ISD::SUB, NVT, Tmp1, 
+                             DAG.getConstant(getSizeInBits(NVT) - 
+                                             getSizeInBits(OVT), NVT));
+        break;
+      }
+      break;
+    }
+    case TargetLowering::Custom:
+      assert(0 && "Cannot custom handle this yet!");
+    case TargetLowering::Expand:
+      assert(0 && "Cannot expand this yet!");
+      break;
+    }
+    break;
+    
     // Unary operators
   case ISD::FABS:
   case ISD::FNEG:
index f9b347d4c938a6c917efbe3ad60835d1afcf8076..f4d7adcc4edee2e966ae070e85874d6a14b00451 100644 (file)
@@ -1328,10 +1328,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
   return SDOperand(N, 0);
 }
 
-SDOperand SelectionDAG::getSrcValue(const Value* v) {
-  SDNode *N = new SrcValueSDNode(v);
+SDOperand SelectionDAG::getSrcValue(const Value* v, int offset) {
+  if (v && ValueNodes[std::make_pair(v,offset)])
+    return SDOperand(ValueNodes[std::make_pair(v,offset)], 0);
+  SDNode *N = new SrcValueSDNode(v, offset);
   N->setValueTypes(MVT::Other);
-  // FIXME: memoize NODES
+  if (v) //only track non-null values
+    ValueNodes[std::make_pair(v,offset)] = N;
   AllNodes.push_back(N);
   return SDOperand(N, 0);
 }
index 20483d48146bbbf63d240228a0cf111720200672..26be6515816a11cb1bd74203b70124e1623afa94 100644 (file)
@@ -707,6 +707,21 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
         DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num));
         return;
       }
+      case Intrinsic::cttz:
+        setValue(&I, DAG.getNode(ISD::CTTZ,
+                                 getValue(I.getOperand(1)).getValueType(),
+                                 getValue(I.getOperand(1))));
+        return;
+      case Intrinsic::ctlz:
+        setValue(&I, DAG.getNode(ISD::CTLZ,
+                                 getValue(I.getOperand(1)).getValueType(),
+                                 getValue(I.getOperand(1))));
+        return;
+      case Intrinsic::ctpop:
+        setValue(&I, DAG.getNode(ISD::CTPOP,
+                                 getValue(I.getOperand(1)).getValueType(),
+                                 getValue(I.getOperand(1))));
+        return;
       }
 
   SDOperand Callee;
index 574f8644eeb29c8baf2cd314f7c031385e3086e9..53d8a9e561ca75941c61ed473cd036292a1c4a9a 100644 (file)
@@ -76,6 +76,10 @@ namespace {
       setOperationAction(ISD::SREM     , MVT::f32  , Expand);
       setOperationAction(ISD::SREM     , MVT::f64  , Expand);
 
+      //      setOperationAction(ISD::CTPOP    , MVT::i64  , Expand);
+      //      setOperationAction(ISD::CTTZ     , MVT::i64  , Expand);
+      //      setOperationAction(ISD::CTTZ     , MVT::i64  , Expand);
+
       //If this didn't legalize into a div....
       //      setOperationAction(ISD::SREM     , MVT::i64, Expand);
       //      setOperationAction(ISD::UREM     , MVT::i64, Expand);
@@ -1215,6 +1219,15 @@ unsigned ISel::SelectExpr(SDOperand N) {
     Node->dump();
     assert(0 && "Node not handled!\n");
 
+  case ISD::CTPOP:
+  case ISD::CTTZ:
+  case ISD::CTLZ:
+    Opc = opcode == ISD::CTPOP ? Alpha::CTPOP :
+    (opcode == ISD::CTTZ ? Alpha::CTTZ : Alpha::CTLZ);
+    Tmp1 = SelectExpr(N.getOperand(0));
+    BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
+    return Result;
+
   case ISD::MULHU:
     Tmp1 = SelectExpr(N.getOperand(0));
     Tmp2 = SelectExpr(N.getOperand(1));
index e341e858cb7f07027bba3a6b05d314947d43dca0..c42ad1ed20f0c371593cd0d11cb06879c9f85ba7 100644 (file)
@@ -186,12 +186,9 @@ def BIC      : OForm< 0x11, 0x08, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "bic $RA,$
 def BICi     : OFormL<0x11, 0x08, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "bic $RA,$L,$RC">; //Bit clear
 def BIS      : OForm< 0x11, 0x20, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "bis $RA,$RB,$RC">; //Logical sum
 def BISi     : OFormL<0x11, 0x20, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "bis $RA,$L,$RC">; //Logical sum
-def CTLZ     : OForm< 0x1C, 0x32, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTLZ $RA,$RB,$RC">; //Count leading zero
-def CTLZi    : OFormL<0x1C, 0x32, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "CTLZ $RA,$L,$RC">; //Count leading zero
-def CTPOP    : OForm< 0x1C, 0x30, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTPOP $RA,$RB,$RC">; //Count population
-def CTPOPi   : OFormL<0x1C, 0x30, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "CTPOP $RA,$L,$RC">; //Count population
-def CTTZ     : OForm< 0x1C, 0x33, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTTZ $RA,$RB,$RC">; //Count trailing zero
-def CTTZi    : OFormL<0x1C, 0x33, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "CTTZ $RA,$L,$RC">; //Count trailing zero
+def CTLZ     : OForm< 0x1C, 0x32, (ops GPRC:$RC, GPRC:$RB), "CTLZ $RB,$RC">; //Count leading zero
+def CTPOP    : OForm< 0x1C, 0x30, (ops GPRC:$RC, GPRC:$RB), "CTPOP $RB,$RC">; //Count population
+def CTTZ     : OForm< 0x1C, 0x33, (ops GPRC:$RC, GPRC:$RB), "CTTZ $RB,$RC">; //Count trailing zero
 def EQV      : OForm< 0x11, 0x48, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "eqv $RA,$RB,$RC">; //Logical equivalence
 def EQVi     : OFormL<0x11, 0x48, (ops GPRC:$RC, GPRC:$RA, u8imm:$L), "eqv $RA,$L,$RC">; //Logical equivalence
 def EXTBL    : OForm< 0x12, 0x06, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTBL $RA,$RB,$RC">; //Extract byte low
index 8614a24743ce0326f3522e3bb9f55c8ff4298eee..25fbb98acdf31bf37476ab8a6991b1a8ce712410 100644 (file)
@@ -68,6 +68,11 @@ namespace {
       setOperationAction(ISD::SREM, MVT::i64, Expand);
       setOperationAction(ISD::UREM, MVT::i64, Expand);
 
+      // PowerPC has these, but they are not implemented
+      setOperationAction(ISD::CTPOP, MVT::i64, Expand);
+      setOperationAction(ISD::CTTZ , MVT::i64, Expand);
+      setOperationAction(ISD::CTTZ , MVT::i64, Expand);
+
       setShiftAmountFlavor(Extend);   // shl X, 32 == 0
       addLegalFPImmediate(+0.0); // Necessary for FSEL
       addLegalFPImmediate(-0.0); //
index a5732f05767ab639db58eb9ff6650ae1f601f7a5..6ed33381f358fa69ce744459425e808a9b707e7c 100644 (file)
@@ -69,6 +69,11 @@ namespace {
       setOperationAction(ISD::FCOS , MVT::f32, Expand);
       setOperationAction(ISD::FSQRT, MVT::f32, Expand);
 
+      //PowerPC has these, but they are not implemented
+      setOperationAction(ISD::CTPOP, MVT::i32  , Expand);
+      setOperationAction(ISD::CTTZ , MVT::i32  , Expand);
+      setOperationAction(ISD::CTTZ , MVT::i32  , Expand);
+
       setSetCCResultContents(ZeroOrOneSetCCResult);
       addLegalFPImmediate(+0.0); // Necessary for FSEL
       addLegalFPImmediate(-0.0); //
index 8b3f31cecfa568b2699553985ea450cce13b6722..07378427497ee5533bdc1600c352e8db944ad2fa 100644 (file)
@@ -64,6 +64,9 @@ namespace {
       setOperationAction(ISD::FP_ROUND_INREG   , MVT::f32  , Expand);
       setOperationAction(ISD::SEXTLOAD         , MVT::i1   , Expand);
       setOperationAction(ISD::SREM             , MVT::f64  , Expand);
+      setOperationAction(ISD::CTPOP            , MVT::i32  , Expand);
+      setOperationAction(ISD::CTTZ             , MVT::i32  , Expand);
+      setOperationAction(ISD::CTTZ             , MVT::i32  , Expand);
 
       if (!UnsafeFPMath) {
         setOperationAction(ISD::FSIN           , MVT::f64  , Expand);
index 6740c6bbb0dec749794b237af9186f7c610cd9d1..f61a4d2326241ce00029c813b7fbb262707a49f6 100644 (file)
@@ -206,6 +206,11 @@ unsigned Function::getIntrinsicID() const {
   assert(getName().size() != 5 && "'llvm.' is an invalid intrinsic name!");
 
   switch (getName()[5]) {
+  case 'c':
+    if (getName() == "llvm.ctpop") return Intrinsic::ctpop;
+    if (getName() == "llvm.cttz") return Intrinsic::cttz;
+    if (getName() == "llvm.ctlz") return Intrinsic::ctlz;
+    break;
   case 'd':
     if (getName() == "llvm.dbg.stoppoint")   return Intrinsic::dbg_stoppoint;
     if (getName() == "llvm.dbg.region.start")return Intrinsic::dbg_region_start;
index d7b8f509621b59e7ef21043f5de3e7f7efabd15a..ab9e60cc3eeba4a4a9edbd00d6cbe772b70f0d7d 100644 (file)
@@ -723,6 +723,18 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
     NumArgs = 2;
     break;
 
+  case Intrinsic::ctpop:
+  case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+    Assert1(FT->getNumParams() == 1,
+            "Illegal # arguments for intrinsic function!", IF);
+    Assert1(FT->getReturnType() == FT->getParamType(0),
+            "Return type does not match source type", IF);
+    Assert1(FT->getParamType(0)->isIntegral(),
+            "Argument must be of an int type!", IF);
+    NumArgs = 1;
+    break;
+
   case Intrinsic::sqrt:
     Assert1(FT->getNumParams() == 1,
             "Illegal # arguments for intrinsic function!", IF);