Implement count leading zeros (ctlz), count trailing zeros (cttz), and count

population (ctpop).  Generic lowering is implemented, however only promotion
is implemented for SelectionDAG at the moment.

More coming soon.

llvm-svn: 21676
This commit is contained in:
Andrew Lenharth 2005-05-03 17:19:30 +00:00
parent f436286cf6
commit 5e177826fd
14 changed files with 326 additions and 14 deletions

View File

@ -44,6 +44,10 @@ class SelectionDAG {
// AllNodes - All of the nodes in the DAG // AllNodes - All of the nodes in the DAG
std::vector<SDNode*> AllNodes; std::vector<SDNode*> AllNodes;
// ValueNodes - track SrcValue nodes
std::map<std::pair<const Value*, int>, SDNode*> ValueNodes;
public: public:
SelectionDAG(TargetLowering &tli, MachineFunction &mf) : TLI(tli), MF(mf) { SelectionDAG(TargetLowering &tli, MachineFunction &mf) : TLI(tli), MF(mf) {
EntryNode = Root = getNode(ISD::EntryToken, MVT::Other); EntryNode = Root = getNode(ISD::EntryToken, MVT::Other);
@ -183,7 +187,7 @@ public:
SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, SDOperand SV); SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, SDOperand SV);
// getSrcValue - construct a node to track a Value* through the backend // 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) { void replaceAllUsesWith(SDOperand Old, SDOperand New) {
assert(Old != New && "RAUW self!"); assert(Old != New && "RAUW self!");

View File

@ -100,6 +100,9 @@ namespace ISD {
// Bitwise operators. // Bitwise operators.
AND, OR, XOR, SHL, SRA, SRL, AND, OR, XOR, SHL, SRA, SRL,
// Counting operators
CTTZ, CTLZ, CTPOP,
// Select operator. // Select operator.
SELECT, SELECT,
@ -546,7 +549,7 @@ protected:
ND = N4.Val->getNodeDepth(); ND = N4.Val->getNodeDepth();
NodeDepth = ND+1; 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); Operands.push_back(N3); Operands.push_back(N4);
N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this); N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this);
N3.Val->Uses.push_back(this); N4.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 { class SrcValueSDNode : public SDNode {
const Value *V; const Value *V;
int offset;
protected: protected:
friend class SelectionDAG; friend class SelectionDAG;
SrcValueSDNode(const Value* v) SrcValueSDNode(const Value* v, int o)
: SDNode(ISD::SRCVALUE, MVT::Other), V(v) {} : SDNode(ISD::SRCVALUE, MVT::Other), V(v), offset(o) {}
public: public:
const Value *getValue() const { return V; } const Value *getValue() const { return V; }
int getOffset() const { return offset; }
static bool classof(const SrcValueSDNode *) { return true; } static bool classof(const SrcValueSDNode *) { return true; }
static bool classof(const SDNode *N) { static bool classof(const SDNode *N) {

View File

@ -63,13 +63,17 @@ namespace Intrinsic {
// libm related functions. // libm related functions.
isunordered, // Return true if either argument is a NaN 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. // Input/Output intrinsics.
readport, readport,
writeport, writeport,
readio, readio,
writeio writeio
}; };
} // End Intrinsic namespace } // End Intrinsic namespace

View File

@ -16,6 +16,7 @@
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/Type.h"
#include <iostream> #include <iostream>
using namespace llvm; using namespace llvm;
@ -164,6 +165,201 @@ void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
AbortFCache); AbortFCache);
break; 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::returnaddress:
case Intrinsic::frameaddress: case Intrinsic::frameaddress:

View File

@ -987,6 +987,51 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
} }
break; 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 // Unary operators
case ISD::FABS: case ISD::FABS:
case ISD::FNEG: case ISD::FNEG:

View File

@ -1328,10 +1328,13 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
return SDOperand(N, 0); return SDOperand(N, 0);
} }
SDOperand SelectionDAG::getSrcValue(const Value* v) { SDOperand SelectionDAG::getSrcValue(const Value* v, int offset) {
SDNode *N = new SrcValueSDNode(v); 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); 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); AllNodes.push_back(N);
return SDOperand(N, 0); return SDOperand(N, 0);
} }

View File

@ -707,6 +707,21 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num)); DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num));
return; 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; SDOperand Callee;

View File

@ -76,6 +76,10 @@ namespace {
setOperationAction(ISD::SREM , MVT::f32 , Expand); setOperationAction(ISD::SREM , MVT::f32 , Expand);
setOperationAction(ISD::SREM , MVT::f64 , 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.... //If this didn't legalize into a div....
// setOperationAction(ISD::SREM , MVT::i64, Expand); // setOperationAction(ISD::SREM , MVT::i64, Expand);
// setOperationAction(ISD::UREM , MVT::i64, Expand); // setOperationAction(ISD::UREM , MVT::i64, Expand);
@ -1215,6 +1219,15 @@ unsigned ISel::SelectExpr(SDOperand N) {
Node->dump(); Node->dump();
assert(0 && "Node not handled!\n"); 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: case ISD::MULHU:
Tmp1 = SelectExpr(N.getOperand(0)); Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1)); Tmp2 = SelectExpr(N.getOperand(1));

View 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 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 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 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 CTLZ : OForm< 0x1C, 0x32, (ops GPRC:$RC, GPRC:$RB), "CTLZ $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:$RB), "CTPOP $RB,$RC">; //Count population
def CTPOP : OForm< 0x1C, 0x30, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "CTPOP $RA,$RB,$RC">; //Count population def CTTZ : OForm< 0x1C, 0x33, (ops GPRC:$RC, GPRC:$RB), "CTTZ $RB,$RC">; //Count trailing zero
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 EQV : OForm< 0x11, 0x48, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "eqv $RA,$RB,$RC">; //Logical equivalence 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 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 def EXTBL : OForm< 0x12, 0x06, (ops GPRC:$RC, GPRC:$RA, GPRC:$RB), "EXTBL $RA,$RB,$RC">; //Extract byte low

View File

@ -69,6 +69,11 @@ namespace {
setOperationAction(ISD::FCOS , MVT::f32, Expand); setOperationAction(ISD::FCOS , MVT::f32, Expand);
setOperationAction(ISD::FSQRT, 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); setSetCCResultContents(ZeroOrOneSetCCResult);
addLegalFPImmediate(+0.0); // Necessary for FSEL addLegalFPImmediate(+0.0); // Necessary for FSEL
addLegalFPImmediate(-0.0); // addLegalFPImmediate(-0.0); //

View File

@ -68,6 +68,11 @@ namespace {
setOperationAction(ISD::SREM, MVT::i64, Expand); setOperationAction(ISD::SREM, MVT::i64, Expand);
setOperationAction(ISD::UREM, 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 setShiftAmountFlavor(Extend); // shl X, 32 == 0
addLegalFPImmediate(+0.0); // Necessary for FSEL addLegalFPImmediate(+0.0); // Necessary for FSEL
addLegalFPImmediate(-0.0); // addLegalFPImmediate(-0.0); //

View File

@ -64,6 +64,9 @@ namespace {
setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand); setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand);
setOperationAction(ISD::SREM , MVT::f64 , 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) { if (!UnsafeFPMath) {
setOperationAction(ISD::FSIN , MVT::f64 , Expand); setOperationAction(ISD::FSIN , MVT::f64 , Expand);

View File

@ -206,6 +206,11 @@ unsigned Function::getIntrinsicID() const {
assert(getName().size() != 5 && "'llvm.' is an invalid intrinsic name!"); assert(getName().size() != 5 && "'llvm.' is an invalid intrinsic name!");
switch (getName()[5]) { 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': case 'd':
if (getName() == "llvm.dbg.stoppoint") return Intrinsic::dbg_stoppoint; if (getName() == "llvm.dbg.stoppoint") return Intrinsic::dbg_stoppoint;
if (getName() == "llvm.dbg.region.start")return Intrinsic::dbg_region_start; if (getName() == "llvm.dbg.region.start")return Intrinsic::dbg_region_start;

View File

@ -723,6 +723,18 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
NumArgs = 2; NumArgs = 2;
break; 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: case Intrinsic::sqrt:
Assert1(FT->getNumParams() == 1, Assert1(FT->getNumParams() == 1,
"Illegal # arguments for intrinsic function!", IF); "Illegal # arguments for intrinsic function!", IF);