diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index f3d41cea15f..a8b42e7155d 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -44,6 +44,10 @@ class SelectionDAG { // AllNodes - All of the nodes in the DAG std::vector AllNodes; + + // ValueNodes - track SrcValue nodes + std::map, 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!"); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index f3be3344a9f..97584d736ae 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -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) { diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h index 7acd5ca71a3..bbf2da36ae4 100644 --- a/include/llvm/Intrinsics.h +++ b/include/llvm/Intrinsics.h @@ -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 diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp index 36f413a14f7..0bad510324e 100644 --- a/lib/CodeGen/IntrinsicLowering.cpp +++ b/lib/CodeGen/IntrinsicLowering.cpp @@ -16,6 +16,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/Instructions.h" +#include "llvm/Type.h" #include 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: diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 52570824c3a..adb88bf9b18 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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: diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index f9b347d4c93..f4d7adcc4ed 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 20483d48146..26be6515816 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -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; diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp index 574f8644eeb..53d8a9e561c 100644 --- a/lib/Target/Alpha/AlphaISelPattern.cpp +++ b/lib/Target/Alpha/AlphaISelPattern.cpp @@ -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)); diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index e341e858cb7..c42ad1ed20f 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -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 diff --git a/lib/Target/PowerPC/PPC64ISelPattern.cpp b/lib/Target/PowerPC/PPC64ISelPattern.cpp index 8614a24743c..25fbb98acdf 100644 --- a/lib/Target/PowerPC/PPC64ISelPattern.cpp +++ b/lib/Target/PowerPC/PPC64ISelPattern.cpp @@ -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); // diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp index a5732f05767..6ed33381f35 100644 --- a/lib/Target/PowerPC/PPCISelPattern.cpp +++ b/lib/Target/PowerPC/PPCISelPattern.cpp @@ -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); // diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 8b3f31cecfa..07378427497 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -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); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 6740c6bbb0d..f61a4d23262 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -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; diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index d7b8f509621..ab9e60cc3ee 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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);