forked from OSchip/llvm-project
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:
parent
f436286cf6
commit
5e177826fd
|
@ -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!");
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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); //
|
||||||
|
|
|
@ -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); //
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue