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
|
||||
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!");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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); //
|
||||
|
|
|
@ -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); //
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue