/// to avoid splitting the same node more than once.
std::map<SDOperand, std::pair<SDOperand, SDOperand> > SplitNodes;
- /// PackedNodes - For nodes that need to be packed from MVT::Vector types to
- /// concrete vector types, this contains the mapping of ones we have already
+ /// ScalarizedNodes - For nodes that need to be converted from vector types to
+ /// scalar types, this contains the mapping of ones we have already
/// processed to the result.
- std::map<SDOperand, SDOperand> PackedNodes;
+ std::map<SDOperand, SDOperand> ScalarizedNodes;
void AddLegalizedOperand(SDOperand From, SDOperand To) {
LegalizedNodes.insert(std::make_pair(From, To));
void LegalizeDAG();
private:
- /// HandleOp - Legalize, Promote, Expand or Pack the specified operand as
+ /// HandleOp - Legalize, Promote, or Expand the specified operand as
/// appropriate for its type.
void HandleOp(SDOperand Op);
/// types.
void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
- /// SplitVectorOp - Given an operand of MVT::Vector type, break it down into
- /// two smaller values of MVT::Vector type.
+ /// SplitVectorOp - Given an operand of vector type, break it down into
+ /// two smaller values.
void SplitVectorOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
- /// PackVectorOp - Given an operand of MVT::Vector type, convert it into the
- /// equivalent operation that returns a packed value (e.g. MVT::V4F32). When
- /// this is called, we know that PackedVT is the right type for the result and
- /// we know that this type is legal for the target.
- SDOperand PackVectorOp(SDOperand O, MVT::ValueType PackedVT);
+ /// ScalarizeVectorOp - Given an operand of single-element vector type
+ /// (e.g. v1f32), convert it into the equivalent operation that returns a
+ /// scalar (e.g. f32) value.
+ SDOperand ScalarizeVectorOp(SDOperand O);
/// isShuffleLegal - Return true if a vector shuffle is legal with the
/// specified mask and type. Targets can specify exactly which masks they
void ExpandShiftParts(unsigned NodeOp, SDOperand Op, SDOperand Amt,
SDOperand &Lo, SDOperand &Hi);
- SDOperand LowerVEXTRACT_VECTOR_ELT(SDOperand Op);
+ SDOperand ExpandEXTRACT_SUBVECTOR(SDOperand Op);
SDOperand ExpandEXTRACT_VECTOR_ELT(SDOperand Op);
SDOperand getIntPtrConstant(uint64_t Val) {
return TLI.isShuffleMaskLegal(Mask, VT) ? Mask.Val : 0;
}
-/// getScalarizedOpcode - Return the scalar opcode that corresponds to the
-/// specified vector opcode.
-static unsigned getScalarizedOpcode(unsigned VecOp, MVT::ValueType VT) {
- switch (VecOp) {
- default: assert(0 && "Don't know how to scalarize this opcode!");
- case ISD::VADD: return MVT::isInteger(VT) ? ISD::ADD : ISD::FADD;
- case ISD::VSUB: return MVT::isInteger(VT) ? ISD::SUB : ISD::FSUB;
- case ISD::VMUL: return MVT::isInteger(VT) ? ISD::MUL : ISD::FMUL;
- case ISD::VSDIV: return MVT::isInteger(VT) ? ISD::SDIV: ISD::FDIV;
- case ISD::VUDIV: return MVT::isInteger(VT) ? ISD::UDIV: ISD::FDIV;
- case ISD::VAND: return MVT::isInteger(VT) ? ISD::AND : 0;
- case ISD::VOR: return MVT::isInteger(VT) ? ISD::OR : 0;
- case ISD::VXOR: return MVT::isInteger(VT) ? ISD::XOR : 0;
- }
-}
-
SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag)
: TLI(dag.getTargetLoweringInfo()), DAG(dag),
ValueTypeActions(TLI.getValueTypeActions()) {
"Too many value types for ValueTypeActions to hold!");
}
-/// ComputeTopDownOrdering - Add the specified node to the Order list if it has
-/// not been visited yet and if all of its operands have already been visited.
-static void ComputeTopDownOrdering(SDNode *N, SmallVector<SDNode*, 64> &Order,
- DenseMap<SDNode*, unsigned> &Visited) {
- if (++Visited[N] != N->getNumOperands())
- return; // Haven't visited all operands yet
-
- Order.push_back(N);
+/// ComputeTopDownOrdering - Compute a top-down ordering of the dag, where Order
+/// contains all of a nodes operands before it contains the node.
+static void ComputeTopDownOrdering(SelectionDAG &DAG,
+ SmallVector<SDNode*, 64> &Order) {
+
+ DenseMap<SDNode*, unsigned> Visited;
+ std::vector<SDNode*> Worklist;
+ Worklist.reserve(128);
- if (N->hasOneUse()) { // Tail recurse in common case.
- ComputeTopDownOrdering(*N->use_begin(), Order, Visited);
- return;
+ // Compute ordering from all of the leaves in the graphs, those (like the
+ // entry node) that have no operands.
+ for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
+ E = DAG.allnodes_end(); I != E; ++I) {
+ if (I->getNumOperands() == 0) {
+ Visited[I] = 0 - 1U;
+ Worklist.push_back(I);
+ }
}
- // Now that we have N in, add anything that uses it if all of their operands
- // are now done.
- for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E;++UI)
- ComputeTopDownOrdering(*UI, Order, Visited);
+ while (!Worklist.empty()) {
+ SDNode *N = Worklist.back();
+ Worklist.pop_back();
+
+ if (++Visited[N] != N->getNumOperands())
+ continue; // Haven't visited all operands yet
+
+ Order.push_back(N);
+
+ // Now that we have N in, add anything that uses it if all of their operands
+ // are now done.
+ for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
+ UI != E; ++UI)
+ Worklist.push_back(*UI);
+ }
+
+ assert(Order.size() == Visited.size() &&
+ Order.size() ==
+ (unsigned)std::distance(DAG.allnodes_begin(), DAG.allnodes_end()) &&
+ "Error: DAG is cyclic!");
}
// practice however, this causes us to run out of stack space on large basic
// blocks. To avoid this problem, compute an ordering of the nodes where each
// node is only legalized after all of its operands are legalized.
- DenseMap<SDNode*, unsigned> Visited;
SmallVector<SDNode*, 64> Order;
-
- // Compute ordering from all of the leaves in the graphs, those (like the
- // entry node) that have no operands.
- for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
- E = DAG.allnodes_end(); I != E; ++I) {
- if (I->getNumOperands() == 0) {
- Visited[I] = 0 - 1U;
- ComputeTopDownOrdering(I, Order, Visited);
- }
- }
-
- assert(Order.size() == Visited.size() &&
- Order.size() ==
- (unsigned)std::distance(DAG.allnodes_begin(), DAG.allnodes_end()) &&
- "Error: DAG is cyclic!");
- Visited.clear();
+ ComputeTopDownOrdering(DAG, Order);
for (unsigned i = 0, e = Order.size(); i != e; ++i)
HandleOp(SDOperand(Order[i], 0));
LegalizedNodes.clear();
PromotedNodes.clear();
SplitNodes.clear();
- PackedNodes.clear();
+ ScalarizedNodes.clear();
// Remove dead nodes now.
DAG.RemoveDeadNodes();
return false;
}
-/// HandleOp - Legalize, Promote, Expand or Pack the specified operand as
+/// HandleOp - Legalize, Promote, or Expand the specified operand as
/// appropriate for its type.
void SelectionDAGLegalize::HandleOp(SDOperand Op) {
- switch (getTypeAction(Op.getValueType())) {
+ MVT::ValueType VT = Op.getValueType();
+ switch (getTypeAction(VT)) {
default: assert(0 && "Bad type action!");
- case Legal: LegalizeOp(Op); break;
- case Promote: PromoteOp(Op); break;
+ case Legal: (void)LegalizeOp(Op); break;
+ case Promote: (void)PromoteOp(Op); break;
case Expand:
- if (Op.getValueType() != MVT::Vector) {
+ if (!MVT::isVector(VT)) {
+ // If this is an illegal scalar, expand it into its two component
+ // pieces.
SDOperand X, Y;
ExpandOp(Op, X, Y);
+ } else if (MVT::getVectorNumElements(VT) == 1) {
+ // If this is an illegal single element vector, convert it to a
+ // scalar operation.
+ (void)ScalarizeVectorOp(Op);
} else {
- SDNode *N = Op.Val;
- unsigned NumOps = N->getNumOperands();
- unsigned NumElements =
- cast<ConstantSDNode>(N->getOperand(NumOps-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(N->getOperand(NumOps-1))->getVT();
- MVT::ValueType PackedVT = getVectorType(EVT, NumElements);
- if (PackedVT != MVT::Other && TLI.isTypeLegal(PackedVT)) {
- // In the common case, this is a legal vector type, convert it to the
- // packed operation and type now.
- PackVectorOp(Op, PackedVT);
- } else if (NumElements == 1) {
- // Otherwise, if this is a single element vector, convert it to a
- // scalar operation.
- PackVectorOp(Op, EVT);
- } else {
- // Otherwise, this is a multiple element vector that isn't supported.
- // Split it in half and legalize both parts.
- SDOperand X, Y;
- SplitVectorOp(Op, X, Y);
- }
+ // Otherwise, this is an illegal multiple element vector.
+ // Split it in half and legalize both parts.
+ SDOperand X, Y;
+ SplitVectorOp(Op, X, Y);
}
break;
}
SelectionDAG &DAG, TargetLowering &TLI) {
MVT::ValueType VT = Node->getValueType(0);
MVT::ValueType SrcVT = Node->getOperand(1).getValueType();
+ assert((SrcVT == MVT::f32 || SrcVT == MVT::f64) &&
+ "fcopysign expansion only supported for f32 and f64");
MVT::ValueType SrcNVT = (SrcVT == MVT::f64) ? MVT::i64 : MVT::i32;
// First get the sign bit of second operand.
case ISD::TargetConstantFP:
case ISD::TargetConstantPool:
case ISD::TargetGlobalAddress:
+ case ISD::TargetGlobalTLSAddress:
case ISD::TargetExternalSymbol:
case ISD::VALUETYPE:
case ISD::SRCVALUE:
case ISD::STRING:
case ISD::CONDCODE:
- case ISD::GLOBAL_OFFSET_TABLE:
// Primitives must all be legal.
assert(TLI.isOperationLegal(Node->getValueType(0), Node->getValueType(0)) &&
"This must be legal!");
}
// Otherwise this is an unhandled builtin node. splat.
#ifndef NDEBUG
- cerr << "NODE: "; Node->dump(); cerr << "\n";
+ cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to legalize this operator!");
abort();
+ case ISD::GLOBAL_OFFSET_TABLE:
case ISD::GlobalAddress:
+ case ISD::GlobalTLSAddress:
case ISD::ExternalSymbol:
case ISD::ConstantPool:
case ISD::JumpTable: // Nothing to do.
Result = TLI.LowerOperation(Op, DAG);
if (Result.Val) break;
// Fall Thru
- case TargetLowering::Legal:
- Result = DAG.getNode(ISD::MERGE_VALUES, VT, DAG.getConstant(0, VT), Tmp1).
- getValue(Op.ResNo);
+ case TargetLowering::Legal: {
+ SDOperand Ops[] = { DAG.getConstant(0, VT), Tmp1 };
+ Result = DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
+ Ops, 2).getValue(Op.ResNo);
break;
}
}
+ }
break;
case ISD::EHSELECTION: {
Tmp1 = LegalizeOp(Node->getOperand(0));
Result = TLI.LowerOperation(Op, DAG);
if (Result.Val) break;
// Fall Thru
- case TargetLowering::Legal:
- Result = DAG.getNode(ISD::MERGE_VALUES, VT, DAG.getConstant(0, VT), Tmp2).
- getValue(Op.ResNo);
+ case TargetLowering::Legal: {
+ SDOperand Ops[] = { DAG.getConstant(0, VT), Tmp2 };
+ Result = DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
+ Ops, 2).getValue(Op.ResNo);
break;
}
}
+ }
break;
case ISD::AssertSext:
case ISD::AssertZext:
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the label id.
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
break;
+ case TargetLowering::Expand:
+ Result = LegalizeOp(Node->getOperand(0));
+ break;
}
break;
unsigned NumElts = MVT::getVectorNumElements(Tmp1.getValueType());
MVT::ValueType ShufMaskVT = MVT::getIntVectorWithNumElements(NumElts);
- MVT::ValueType ShufMaskEltVT = MVT::getVectorBaseType(ShufMaskVT);
+ MVT::ValueType ShufMaskEltVT = MVT::getVectorElementType(ShufMaskVT);
// We generate a shuffle of InVec and ScVec, so the shuffle mask should
// be 0,1,2,3,4,5... with the appropriate element replaced with elt 0 of
// FALLTHROUGH
case TargetLowering::Expand: {
MVT::ValueType VT = Node->getValueType(0);
- MVT::ValueType EltVT = MVT::getVectorBaseType(VT);
+ MVT::ValueType EltVT = MVT::getVectorElementType(VT);
MVT::ValueType PtrVT = TLI.getPointerTy();
SDOperand Mask = Node->getOperand(2);
unsigned NumElems = Mask.getNumOperands();
break;
case ISD::EXTRACT_VECTOR_ELT:
- Tmp1 = LegalizeOp(Node->getOperand(0));
+ Tmp1 = Node->getOperand(0);
Tmp2 = LegalizeOp(Node->getOperand(1));
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
-
- switch (TLI.getOperationAction(ISD::EXTRACT_VECTOR_ELT,
- Tmp1.getValueType())) {
- default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal:
- break;
- case TargetLowering::Custom:
- Tmp3 = TLI.LowerOperation(Result, DAG);
- if (Tmp3.Val) {
- Result = Tmp3;
- break;
- }
- // FALLTHROUGH
- case TargetLowering::Expand:
- Result = ExpandEXTRACT_VECTOR_ELT(Result);
- break;
- }
+ Result = ExpandEXTRACT_VECTOR_ELT(Result);
break;
- case ISD::VEXTRACT_VECTOR_ELT:
- Result = LegalizeOp(LowerVEXTRACT_VECTOR_ELT(Op));
+ case ISD::EXTRACT_SUBVECTOR:
+ Tmp1 = Node->getOperand(0);
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ Result = ExpandEXTRACT_SUBVECTOR(Result);
break;
case ISD::CALLSEQ_START: {
// The top bits of the promoted condition are not necessarily zero, ensure
// that the value is properly zero extended.
- if (!TLI.MaskedValueIsZero(Tmp2,
+ if (!DAG.MaskedValueIsZero(Tmp2,
MVT::getIntVTBitMask(Tmp2.getValueType())^1))
Tmp2 = DAG.getZeroExtendInReg(Tmp2, MVT::i1);
break;
Result = DAG.UpdateNodeOperands(Result, Tmp1, LegalizeOp(Tmp2), Tmp3);
break;
case Expand:
- if (Tmp2.getValueType() != MVT::Vector) {
+ if (!MVT::isVector(Tmp2.getValueType())) {
SDOperand Lo, Hi;
ExpandOp(Tmp2, Lo, Hi);
+
+ // Big endian systems want the hi reg first.
+ if (!TLI.isLittleEndian())
+ std::swap(Lo, Hi);
+
if (Hi.Val)
Result = DAG.getNode(ISD::RET, MVT::Other, Tmp1, Lo, Tmp3, Hi,Tmp3);
else
Result = LegalizeOp(Result);
} else {
SDNode *InVal = Tmp2.Val;
- unsigned NumElems =
- cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
- // Figure out if there is a Packed type corresponding to this Vector
+ // Figure out if there is a simple type corresponding to this Vector
// type. If so, convert to the vector type.
MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) {
+ if (TLI.isTypeLegal(TVT)) {
// Turn this into a return of the vector type.
- Tmp2 = PackVectorOp(Tmp2, TVT);
+ Tmp2 = LegalizeOp(Tmp2);
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
} else if (NumElems == 1) {
// Turn this into a return of the scalar type.
- Tmp2 = PackVectorOp(Tmp2, EVT);
+ Tmp2 = ScalarizeVectorOp(Tmp2);
+ Tmp2 = LegalizeOp(Tmp2);
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
// FIXME: Returns of gcc generic vectors smaller than a legal type
break;
case Expand: {
SDOperand Lo, Hi;
- assert(Node->getOperand(i).getValueType() != MVT::Vector &&
+ assert(!MVT::isExtendedVT(Node->getOperand(i).getValueType()) &&
"FIXME: TODO: implement returning non-legal vector types!");
ExpandOp(Node->getOperand(i), Lo, Hi);
NewValues.push_back(Lo);
// If this is a vector type, then we have to calculate the increment as
// the product of the element size in bytes, and the number of elements
// in the high half of the vector.
- if (ST->getValue().getValueType() == MVT::Vector) {
+ if (MVT::isVector(ST->getValue().getValueType())) {
SDNode *InVal = ST->getValue().Val;
- unsigned NumElems =
- cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
- // Figure out if there is a Packed type corresponding to this Vector
+ // Figure out if there is a simple type corresponding to this Vector
// type. If so, convert to the vector type.
MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) {
+ if (TLI.isTypeLegal(TVT)) {
// Turn this into a normal store of the vector type.
- Tmp3 = PackVectorOp(Node->getOperand(1), TVT);
+ Tmp3 = LegalizeOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- ST->getSrcValueOffset());
+ ST->getSrcValueOffset(),
+ ST->isVolatile(),
+ ST->getAlignment());
Result = LegalizeOp(Result);
break;
} else if (NumElems == 1) {
// Turn this into a normal store of the scalar type.
- Tmp3 = PackVectorOp(Node->getOperand(1), EVT);
+ Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- ST->getSrcValueOffset());
+ ST->getSrcValueOffset(),
+ ST->isVolatile(),
+ ST->getAlignment());
// The scalarized value type may not be legal, e.g. it might require
// promotion or expansion. Relegalize the scalar store.
Result = LegalizeOp(Result);
}
Lo = DAG.getStore(Tmp1, Lo, Tmp2, ST->getSrcValue(),
- ST->getSrcValueOffset());
+ ST->getSrcValueOffset(), ST->isVolatile(),
+ ST->getAlignment());
if (Hi.Val == NULL) {
// Must be int <-> float one-to-one expansion.
// FIXME: This sets the srcvalue of both halves to be the same, which is
// wrong.
Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(),
- ST->getSrcValueOffset());
+ ST->getSrcValueOffset(), ST->isVolatile(),
+ std::min(ST->getAlignment(), IncrementSize));
Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
break;
}
case Promote:
Tmp1 = PromoteOp(Node->getOperand(0)); // Promote the condition.
// Make sure the condition is either zero or one.
- if (!TLI.MaskedValueIsZero(Tmp1,
+ if (!DAG.MaskedValueIsZero(Tmp1,
MVT::getIntVTBitMask(Tmp1.getValueType())^1))
Tmp1 = DAG.getZeroExtendInReg(Tmp1, MVT::i1);
break;
const char *FnName = 0;
if (Node->getOpcode() == ISD::MEMSET) {
- Entry.Node = Tmp2; Entry.isSigned = false; Entry.Ty = IntPtrTy;
- Entry.isInReg = false; Entry.isSRet = false;
+ Entry.Node = Tmp2; Entry.Ty = IntPtrTy;
Args.push_back(Entry);
// Extend the (previously legalized) ubyte argument to be an int value
// for the call.
Tmp3 = DAG.getNode(ISD::TRUNCATE, MVT::i32, Tmp3);
else
Tmp3 = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Tmp3);
- Entry.Node = Tmp3; Entry.Ty = Type::Int32Ty; Entry.isSigned = true;
- Entry.isInReg = false; Entry.isSRet = false;
+ Entry.Node = Tmp3; Entry.Ty = Type::Int32Ty; Entry.isSExt = true;
Args.push_back(Entry);
- Entry.Node = Tmp4; Entry.Ty = IntPtrTy; Entry.isSigned = false;
+ Entry.Node = Tmp4; Entry.Ty = IntPtrTy; Entry.isSExt = false;
Args.push_back(Entry);
FnName = "memset";
} else if (Node->getOpcode() == ISD::MEMCPY ||
Node->getOpcode() == ISD::MEMMOVE) {
Entry.Ty = IntPtrTy;
- Entry.isSigned = false; Entry.isInReg = false; Entry.isSRet = false;
Entry.Node = Tmp2; Args.push_back(Entry);
Entry.Node = Tmp3; Args.push_back(Entry);
Entry.Node = Tmp4; Args.push_back(Entry);
"Cannot expand this binary operator!");
// Expand the operation into a bunch of nasty scalar code.
SmallVector<SDOperand, 8> Ops;
- MVT::ValueType EltVT = MVT::getVectorBaseType(Node->getValueType(0));
+ MVT::ValueType EltVT = MVT::getVectorElementType(Node->getValueType(0));
MVT::ValueType PtrVT = TLI.getPointerTy();
for (unsigned i = 0, e = MVT::getVectorNumElements(Node->getValueType(0));
i != e; ++i) {
case ISD::ROTR:
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS
-
- assert(TLI.isOperationLegal(Node->getOpcode(), Node->getValueType(0)) &&
- "Cannot handle this yet!");
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+ default:
+ assert(0 && "ROTL/ROTR legalize operation not supported");
+ break;
+ case TargetLowering::Legal:
+ break;
+ case TargetLowering::Custom:
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.Val) Result = Tmp1;
+ break;
+ case TargetLowering::Promote:
+ assert(0 && "Do not know how to promote ROTL/ROTR");
+ break;
+ case TargetLowering::Expand:
+ assert(0 && "Do not know how to expand ROTL/ROTR");
+ break;
+ }
break;
case ISD::BSWAP:
case TargetLowering::Promote: {
MVT::ValueType OVT = Tmp1.getValueType();
MVT::ValueType NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT);
- unsigned DiffBits = getSizeInBits(NVT) - getSizeInBits(OVT);
+ unsigned DiffBits = MVT::getSizeInBits(NVT) - MVT::getSizeInBits(OVT);
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, NVT, Tmp1);
Tmp1 = DAG.getNode(ISD::BSWAP, NVT, Tmp1);
case ISD::CTTZ:
//if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT)
Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), Tmp1,
- DAG.getConstant(getSizeInBits(NVT), NVT),
+ DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
ISD::SETEQ);
Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
- DAG.getConstant(getSizeInBits(OVT),NVT), Tmp1);
+ DAG.getConstant(MVT::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));
+ DAG.getConstant(MVT::getSizeInBits(NVT) -
+ MVT::getSizeInBits(OVT), NVT));
break;
}
break;
case ISD::BIT_CONVERT:
if (!isTypeLegal(Node->getOperand(0).getValueType())) {
Result = ExpandBIT_CONVERT(Node->getValueType(0), Node->getOperand(0));
+ } else if (MVT::isVector(Op.getOperand(0).getValueType())) {
+ // The input has to be a vector type, we have to either scalarize it, pack
+ // it, or convert it based on whether the input vector type is legal.
+ SDNode *InVal = Node->getOperand(0).Val;
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+
+ // Figure out if there is a simple type corresponding to this Vector
+ // type. If so, convert to the vector type.
+ MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
+ if (TLI.isTypeLegal(TVT)) {
+ // Turn this into a bit convert of the packed input.
+ Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
+ LegalizeOp(Node->getOperand(0)));
+ break;
+ } else if (NumElems == 1) {
+ // Turn this into a bit convert of the scalar input.
+ Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
+ ScalarizeVectorOp(Node->getOperand(0)));
+ break;
+ } else {
+ // FIXME: UNIMP! Store then reload
+ assert(0 && "Cast from unsupported vector type not implemented yet!");
+ }
} else {
switch (TLI.getOperationAction(ISD::BIT_CONVERT,
Node->getOperand(0).getValueType())) {
}
}
break;
- case ISD::VBIT_CONVERT: {
- assert(Op.getOperand(0).getValueType() == MVT::Vector &&
- "Can only have VBIT_CONVERT where input or output is MVT::Vector!");
-
- // The input has to be a vector type, we have to either scalarize it, pack
- // it, or convert it based on whether the input vector type is legal.
- SDNode *InVal = Node->getOperand(0).Val;
- unsigned NumElems =
- cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
-
- // Figure out if there is a Packed type corresponding to this Vector
- // type. If so, convert to the vector type.
- MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) {
- // Turn this into a bit convert of the packed input.
- Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
- PackVectorOp(Node->getOperand(0), TVT));
- break;
- } else if (NumElems == 1) {
- // Turn this into a bit convert of the scalar input.
- Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
- PackVectorOp(Node->getOperand(0), EVT));
- break;
- } else {
- // FIXME: UNIMP! Store then reload
- assert(0 && "Cast from unsupported vector type not implemented yet!");
- }
- }
// Conversion operators. The source and destination have different types.
case ISD::SINT_TO_FP:
// slots and always reusing the same one. We currently always create
// new ones, as reuse may inhibit scheduling.
const Type *Ty = MVT::getTypeForValueType(ExtraVT);
- unsigned TySize = (unsigned)TLI.getTargetData()->getTypeSize(Ty);
+ uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
MachineFunction &MF = DAG.getMachineFunction();
int SSFI =
- MF.getFrameInfo()->CreateStackObject((unsigned)TySize, Align);
+ MF.getFrameInfo()->CreateStackObject(TySize, Align);
SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
StackSlot, NULL, 0, ExtraVT);
assert(0 && "CopyFromReg must be legal!");
default:
#ifndef NDEBUG
- cerr << "NODE: "; Node->dump(); cerr << "\n";
+ cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to promote this operator!");
abort();
DAG.getValueType(VT));
break;
+ case ISD::FPOWI: {
+ // Promote f32 powi to f64 powi. Note that this could insert a libcall
+ // directly as well, which may be better.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ assert(Tmp1.getValueType() == NVT);
+ Result = DAG.getNode(ISD::FPOWI, NVT, Tmp1, Node->getOperand(1));
+ if (NoExcessFPPrecision)
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result,
+ DAG.getValueType(VT));
+ break;
+ }
+
case ISD::AND:
case ISD::OR:
case ISD::XOR:
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, NVT, Tmp1);
Tmp1 = DAG.getNode(ISD::BSWAP, NVT, Tmp1);
Result = DAG.getNode(ISD::SRL, NVT, Tmp1,
- DAG.getConstant(getSizeInBits(NVT) - getSizeInBits(VT),
+ DAG.getConstant(MVT::getSizeInBits(NVT) -
+ MVT::getSizeInBits(VT),
TLI.getShiftAmountTy()));
break;
case ISD::CTPOP:
case ISD::CTTZ:
// if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT)
Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), Tmp1,
- DAG.getConstant(getSizeInBits(NVT), NVT), ISD::SETEQ);
+ DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
+ ISD::SETEQ);
Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
- DAG.getConstant(getSizeInBits(VT), NVT), Tmp1);
+ DAG.getConstant(MVT::getSizeInBits(VT), 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(VT), NVT));
+ DAG.getConstant(MVT::getSizeInBits(NVT) -
+ MVT::getSizeInBits(VT), NVT));
break;
}
break;
- case ISD::VEXTRACT_VECTOR_ELT:
- Result = PromoteOp(LowerVEXTRACT_VECTOR_ELT(Op));
+ case ISD::EXTRACT_SUBVECTOR:
+ Result = PromoteOp(ExpandEXTRACT_SUBVECTOR(Op));
break;
case ISD::EXTRACT_VECTOR_ELT:
Result = PromoteOp(ExpandEXTRACT_VECTOR_ELT(Op));
return Result;
}
-/// LowerVEXTRACT_VECTOR_ELT - Lower a VEXTRACT_VECTOR_ELT operation into a
-/// EXTRACT_VECTOR_ELT operation, to memory operations, or to scalar code based
-/// on the vector type. The return type of this matches the element type of the
-/// vector, which may not be legal for the target.
-SDOperand SelectionDAGLegalize::LowerVEXTRACT_VECTOR_ELT(SDOperand Op) {
+/// ExpandEXTRACT_VECTOR_ELT - Expand an EXTRACT_VECTOR_ELT operation into
+/// a legal EXTRACT_VECTOR_ELT operation, scalar code, or memory traffic,
+/// based on the vector type. The return type of this matches the element type
+/// of the vector, which may not be legal for the target.
+SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
// We know that operand #0 is the Vec vector. If the index is a constant
// or if the invec is a supported hardware type, we can use it. Otherwise,
// lower to a store then an indexed load.
SDOperand Vec = Op.getOperand(0);
- SDOperand Idx = LegalizeOp(Op.getOperand(1));
+ SDOperand Idx = Op.getOperand(1);
SDNode *InVal = Vec.Val;
- unsigned NumElems = cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
+ MVT::ValueType TVT = InVal->getValueType(0);
+ unsigned NumElems = MVT::getVectorNumElements(TVT);
- // Figure out if there is a Packed type corresponding to this Vector
- // type. If so, convert to the vector type.
- MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) {
- // Turn this into a packed extract_vector_elt operation.
- Vec = PackVectorOp(Vec, TVT);
- return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, Op.getValueType(), Vec, Idx);
- } else if (NumElems == 1) {
+ switch (TLI.getOperationAction(ISD::EXTRACT_VECTOR_ELT, TVT)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Custom: {
+ Vec = LegalizeOp(Vec);
+ Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
+ SDOperand Tmp3 = TLI.LowerOperation(Op, DAG);
+ if (Tmp3.Val)
+ return Tmp3;
+ break;
+ }
+ case TargetLowering::Legal:
+ if (isTypeLegal(TVT)) {
+ Vec = LegalizeOp(Vec);
+ Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
+ Op = LegalizeOp(Op);
+ }
+ break;
+ case TargetLowering::Expand:
+ break;
+ }
+
+ if (NumElems == 1) {
// This must be an access of the only element. Return it.
- return PackVectorOp(Vec, EVT);
- } else if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
+ Op = ScalarizeVectorOp(Vec);
+ } else if (!TLI.isTypeLegal(TVT) && isa<ConstantSDNode>(Idx)) {
+ ConstantSDNode *CIdx = cast<ConstantSDNode>(Idx);
SDOperand Lo, Hi;
SplitVectorOp(Vec, Lo, Hi);
if (CIdx->getValue() < NumElems/2) {
Vec = Lo;
} else {
Vec = Hi;
- Idx = DAG.getConstant(CIdx->getValue() - NumElems/2, Idx.getValueType());
+ Idx = DAG.getConstant(CIdx->getValue() - NumElems/2,
+ Idx.getValueType());
}
-
+
// It's now an extract from the appropriate high or low part. Recurse.
Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
- return LowerVEXTRACT_VECTOR_ELT(Op);
+ Op = ExpandEXTRACT_VECTOR_ELT(Op);
} else {
- // Variable index case for extract element.
- // FIXME: IMPLEMENT STORE/LOAD lowering. Need alignment of stack slot!!
- assert(0 && "unimp!");
- return SDOperand();
+ // Store the value to a temporary stack slot, then LOAD the scalar
+ // element back out.
+ SDOperand StackPtr = CreateStackTemporary(Vec.getValueType());
+ SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
+
+ // Add the offset to the index.
+ unsigned EltSize = MVT::getSizeInBits(Op.getValueType())/8;
+ Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx,
+ DAG.getConstant(EltSize, Idx.getValueType()));
+ StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr);
+
+ Op = DAG.getLoad(Op.getValueType(), Ch, StackPtr, NULL, 0);
}
+ return Op;
}
-/// ExpandEXTRACT_VECTOR_ELT - Expand an EXTRACT_VECTOR_ELT operation into
-/// memory traffic.
-SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
- SDOperand Vector = Op.getOperand(0);
- SDOperand Idx = Op.getOperand(1);
+/// ExpandEXTRACT_SUBVECTOR - Expand a EXTRACT_SUBVECTOR operation. For now
+/// we assume the operation can be split if it is not already legal.
+SDOperand SelectionDAGLegalize::ExpandEXTRACT_SUBVECTOR(SDOperand Op) {
+ // We know that operand #0 is the Vec vector. For now we assume the index
+ // is a constant and that the extracted result is a supported hardware type.
+ SDOperand Vec = Op.getOperand(0);
+ SDOperand Idx = LegalizeOp(Op.getOperand(1));
- // If the target doesn't support this, store the value to a temporary
- // stack slot, then LOAD the scalar element back out.
- SDOperand StackPtr = CreateStackTemporary(Vector.getValueType());
- SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Vector, StackPtr, NULL, 0);
+ unsigned NumElems = MVT::getVectorNumElements(Vec.getValueType());
- // Add the offset to the index.
- unsigned EltSize = MVT::getSizeInBits(Op.getValueType())/8;
- Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx,
- DAG.getConstant(EltSize, Idx.getValueType()));
- StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr);
+ if (NumElems == MVT::getVectorNumElements(Op.getValueType())) {
+ // This must be an access of the desired vector length. Return it.
+ return Vec;
+ }
+
+ ConstantSDNode *CIdx = cast<ConstantSDNode>(Idx);
+ SDOperand Lo, Hi;
+ SplitVectorOp(Vec, Lo, Hi);
+ if (CIdx->getValue() < NumElems/2) {
+ Vec = Lo;
+ } else {
+ Vec = Hi;
+ Idx = DAG.getConstant(CIdx->getValue() - NumElems/2, Idx.getValueType());
+ }
- return DAG.getLoad(Op.getValueType(), Ch, StackPtr, NULL, 0);
+ // It's now an extract from the appropriate high or low part. Recurse.
+ Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
+ return ExpandEXTRACT_SUBVECTOR(Op);
}
-
/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC
/// with condition CC on the current target. This usually involves legalizing
/// or promoting the arguments. In the case where LHS and RHS must be expanded,
// Build the shuffle constant vector: <0, 0, 0, 0>
MVT::ValueType MaskVT =
MVT::getIntVectorWithNumElements(NumElems);
- SDOperand Zero = DAG.getConstant(0, MVT::getVectorBaseType(MaskVT));
+ SDOperand Zero = DAG.getConstant(0, MVT::getVectorElementType(MaskVT));
std::vector<SDOperand> ZeroVec(NumElems, Zero);
SDOperand SplatMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
&ZeroVec[0], ZeroVec.size());
E = Values.end(); I != E; ++I) {
for (std::vector<unsigned>::iterator II = I->second.begin(),
EE = I->second.end(); II != EE; ++II)
- MaskVec[*II] = DAG.getConstant(i, MVT::getVectorBaseType(MaskVT));
+ MaskVec[*II] = DAG.getConstant(i, MVT::getVectorElementType(MaskVT));
i += NumElems;
}
SDOperand ShuffleMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
// Okay, the shift amount isn't constant. However, if we can tell that it is
// >= 32 or < 32, we can still simplify it, without knowing the actual value.
uint64_t Mask = NVTBits, KnownZero, KnownOne;
- TLI.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
+ DAG.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
// If we know that the high bit of the shift amount is one, then we can do
// this as a couple of simple shifts.
MVT::ValueType ArgVT = Node->getOperand(i).getValueType();
const Type *ArgTy = MVT::getTypeForValueType(ArgVT);
Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy;
- Entry.isSigned = isSigned; Entry.isInReg = false; Entry.isSRet = false;
+ Entry.isSExt = isSigned;
Args.push_back(Entry);
}
SDOperand Callee = DAG.getExternalSymbol(Name, TLI.getPointerTy());
}
-/// ExpandIntToFP - Expand a [US]INT_TO_FP operation, assuming that the
-/// destination type is legal.
+/// ExpandIntToFP - Expand a [US]INT_TO_FP operation.
+///
SDOperand SelectionDAGLegalize::
ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) {
- assert(isTypeLegal(DestTy) && "Destination type is not legal!");
assert(getTypeAction(Source.getValueType()) == Expand &&
"This is not an expansion!");
assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
else {
assert(DestTy == MVT::f64 && "Unexpected conversion");
+ // FIXME: Avoid the extend by construction the right constantpool?
FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
CPIdx, NULL, 0, MVT::f32);
}
+ MVT::ValueType SCVT = SignedConv.getValueType();
+ if (SCVT != DestTy) {
+ // Destination type needs to be expanded as well. The FADD now we are
+ // constructing will be expanded into a libcall.
+ if (MVT::getSizeInBits(SCVT) != MVT::getSizeInBits(DestTy)) {
+ assert(SCVT == MVT::i32 && DestTy == MVT::f64);
+ SignedConv = DAG.getNode(ISD::BUILD_PAIR, MVT::i64,
+ SignedConv, SignedConv.getValue(1));
+ }
+ SignedConv = DAG.getNode(ISD::BIT_CONVERT, DestTy, SignedConv);
+ }
return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
}
LC = RTLIB::SINTTOFP_I64_F64;
}
+ assert(TLI.getLibcallName(LC) && "Don't know how to expand this SINT_TO_FP!");
Source = DAG.getNode(ISD::SINT_TO_FP, DestTy, Source);
SDOperand UnusedHiPart;
return ExpandLibCall(TLI.getLibcallName(LC), Source.Val, isSigned,
};
MVT::ValueType VT = Op.getValueType();
MVT::ValueType ShVT = TLI.getShiftAmountTy();
- unsigned len = getSizeInBits(VT);
+ unsigned len = MVT::getSizeInBits(VT);
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
//x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8])
SDOperand Tmp2 = DAG.getConstant(mask[i], VT);
// but see also: http://www.hackersdelight.org/HDcode/nlz.cc
MVT::ValueType VT = Op.getValueType();
MVT::ValueType ShVT = TLI.getShiftAmountTy();
- unsigned len = getSizeInBits(VT);
+ unsigned len = MVT::getSizeInBits(VT);
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT);
Op = DAG.getNode(ISD::OR, VT, Op, DAG.getNode(ISD::SRL, VT, Op, Tmp3));
if (!TLI.isOperationLegal(ISD::CTPOP, VT) &&
TLI.isOperationLegal(ISD::CTLZ, VT))
return DAG.getNode(ISD::SUB, VT,
- DAG.getConstant(getSizeInBits(VT), VT),
+ DAG.getConstant(MVT::getSizeInBits(VT), VT),
DAG.getNode(ISD::CTLZ, VT, Tmp3));
return DAG.getNode(ISD::CTPOP, VT, Tmp3);
}
SDNode *Node = Op.Val;
assert(getTypeAction(VT) == Expand && "Not an expanded type!");
assert(((MVT::isInteger(NVT) && NVT < VT) || MVT::isFloatingPoint(VT) ||
- VT == MVT::Vector) &&
+ MVT::isVector(VT)) &&
"Cannot expand to FP value or to larger int value!");
// See if we already expanded it.
assert(0 && "CopyFromReg must be legal!");
default:
#ifndef NDEBUG
- cerr << "NODE: "; Node->dump(); cerr << "\n";
+ cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to expand this operator!");
abort();
SDOperand Ch = LD->getChain(); // Legalize the chain.
SDOperand Ptr = LD->getBasePtr(); // Legalize the pointer.
ISD::LoadExtType ExtType = LD->getExtensionType();
+ unsigned SVOffset = LD->getSrcValueOffset();
if (ExtType == ISD::NON_EXTLOAD) {
- Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(),LD->getSrcValueOffset());
+ Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset);
if (VT == MVT::f32 || VT == MVT::f64) {
// f32->i32 or f64->i64 one to one expansion.
// Remember that we legalized the chain.
unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
- // FIXME: This creates a bogus srcvalue!
- Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(),LD->getSrcValueOffset());
+ SVOffset += IncrementSize;
+ Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset);
// Build a factor node to remember that this load is independent of the
// other one.
if (VT == MVT::f64 && EVT == MVT::f32) {
// f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
SDOperand Load = DAG.getLoad(EVT, Ch, Ptr, LD->getSrcValue(),
- LD->getSrcValueOffset());
+ SVOffset);
// Remember that we legalized the chain.
AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Load.getValue(1)));
ExpandOp(DAG.getNode(ISD::FP_EXTEND, VT, Load), Lo, Hi);
if (EVT == NVT)
Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(),
- LD->getSrcValueOffset());
+ SVOffset);
else
Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, LD->getSrcValue(),
- LD->getSrcValueOffset(), EVT);
+ SVOffset, EVT);
// Remember that we legalized the chain.
AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
}
break;
}
+
+ case ISD::ADDC:
+ case ISD::SUBC: {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH, RHSL, RHSH;
+ ExpandOp(Node->getOperand(0), LHSL, LHSH);
+ ExpandOp(Node->getOperand(1), RHSL, RHSH);
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[2] = { LHSL, RHSL };
+ SDOperand HiOps[3] = { LHSH, RHSH };
+
+ if (Node->getOpcode() == ISD::ADDC) {
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+ } else {
+ Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+ }
+ // Remember that we legalized the flag.
+ AddLegalizedOperand(Op.getValue(1), LegalizeOp(Hi.getValue(1)));
+ break;
+ }
+ case ISD::ADDE:
+ case ISD::SUBE: {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH, RHSL, RHSH;
+ ExpandOp(Node->getOperand(0), LHSL, LHSH);
+ ExpandOp(Node->getOperand(1), RHSL, RHSH);
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[3] = { LHSL, RHSL, Node->getOperand(2) };
+ SDOperand HiOps[3] = { LHSH, RHSH };
+
+ Lo = DAG.getNode(Node->getOpcode(), VTList, LoOps, 3);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(Node->getOpcode(), VTList, HiOps, 3);
+
+ // Remember that we legalized the flag.
+ AddLegalizedOperand(Op.getValue(1), LegalizeOp(Hi.getValue(1)));
+ break;
+ }
case ISD::MUL: {
// If the target wants to custom expand this, let them.
if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) {
: DAG.getZeroExtendInReg(Tmp, SrcVT);
Node = DAG.UpdateNodeOperands(Op, Tmp).Val;
}
- Lo = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Hi);
+
+ const char *LibCall = TLI.getLibcallName(LC);
+ if (LibCall)
+ Lo = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Hi);
+ else {
+ Lo = ExpandIntToFP(Node->getOpcode() == ISD::SINT_TO_FP, VT,
+ Node->getOperand(0));
+ if (getTypeAction(Lo.getValueType()) == Expand)
+ ExpandOp(Lo, Lo, Hi);
+ }
break;
}
}
assert(isNew && "Value already expanded?!?");
}
-/// SplitVectorOp - Given an operand of MVT::Vector type, break it down into
-/// two smaller values of MVT::Vector type.
+/// SplitVectorOp - Given an operand of vector type, break it down into
+/// two smaller values, still of vector type.
void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
- assert(Op.getValueType() == MVT::Vector && "Cannot split non-vector type!");
+ assert(MVT::isVector(Op.getValueType()) && "Cannot split non-vector type!");
SDNode *Node = Op.Val;
- unsigned NumElements = cast<ConstantSDNode>(*(Node->op_end()-2))->getValue();
+ unsigned NumElements = MVT::getVectorNumElements(Node->getValueType(0));
assert(NumElements > 1 && "Cannot split a single element vector!");
unsigned NewNumElts = NumElements/2;
- SDOperand NewNumEltsNode = DAG.getConstant(NewNumElts, MVT::i32);
- SDOperand TypeNode = *(Node->op_end()-1);
+ MVT::ValueType NewEltVT = MVT::getVectorElementType(Node->getValueType(0));
+ MVT::ValueType NewVT = MVT::getVectorType(NewEltVT, NewNumElts);
// See if we already split it.
std::map<SDOperand, std::pair<SDOperand, SDOperand> >::iterator I
switch (Node->getOpcode()) {
default:
#ifndef NDEBUG
- Node->dump();
+ Node->dump(&DAG);
#endif
assert(0 && "Unhandled operation in SplitVectorOp!");
- case ISD::VBUILD_VECTOR: {
+ case ISD::BUILD_PAIR:
+ Lo = Node->getOperand(0);
+ Hi = Node->getOperand(1);
+ break;
+ case ISD::BUILD_VECTOR: {
SmallVector<SDOperand, 8> LoOps(Node->op_begin(),
Node->op_begin()+NewNumElts);
- LoOps.push_back(NewNumEltsNode);
- LoOps.push_back(TypeNode);
- Lo = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &LoOps[0], LoOps.size());
+ Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &LoOps[0], LoOps.size());
SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumElts,
- Node->op_end()-2);
- HiOps.push_back(NewNumEltsNode);
- HiOps.push_back(TypeNode);
- Hi = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &HiOps[0], HiOps.size());
+ Node->op_end());
+ Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &HiOps[0], HiOps.size());
break;
}
- case ISD::VADD:
- case ISD::VSUB:
- case ISD::VMUL:
- case ISD::VSDIV:
- case ISD::VUDIV:
- case ISD::VAND:
- case ISD::VOR:
- case ISD::VXOR: {
+ case ISD::CONCAT_VECTORS: {
+ unsigned NewNumSubvectors = Node->getNumOperands() / 2;
+ if (NewNumSubvectors == 1) {
+ Lo = Node->getOperand(0);
+ Hi = Node->getOperand(1);
+ } else {
+ SmallVector<SDOperand, 8> LoOps(Node->op_begin(),
+ Node->op_begin()+NewNumSubvectors);
+ Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &LoOps[0], LoOps.size());
+
+ SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumSubvectors,
+ Node->op_end());
+ Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &HiOps[0], HiOps.size());
+ }
+ break;
+ }
+ case ISD::ADD:
+ case ISD::SUB:
+ case ISD::MUL:
+ case ISD::FADD:
+ case ISD::FSUB:
+ case ISD::FMUL:
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::FDIV:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR: {
SDOperand LL, LH, RL, RH;
SplitVectorOp(Node->getOperand(0), LL, LH);
SplitVectorOp(Node->getOperand(1), RL, RH);
- Lo = DAG.getNode(Node->getOpcode(), MVT::Vector, LL, RL,
- NewNumEltsNode, TypeNode);
- Hi = DAG.getNode(Node->getOpcode(), MVT::Vector, LH, RH,
- NewNumEltsNode, TypeNode);
+ Lo = DAG.getNode(Node->getOpcode(), NewVT, LL, RL);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT, LH, RH);
break;
}
- case ISD::VLOAD: {
- SDOperand Ch = Node->getOperand(0); // Legalize the chain.
- SDOperand Ptr = Node->getOperand(1); // Legalize the pointer.
- MVT::ValueType EVT = cast<VTSDNode>(TypeNode)->getVT();
-
- Lo = DAG.getVecLoad(NewNumElts, EVT, Ch, Ptr, Node->getOperand(2));
- unsigned IncrementSize = NewNumElts * MVT::getSizeInBits(EVT)/8;
+ case ISD::LOAD: {
+ LoadSDNode *LD = cast<LoadSDNode>(Node);
+ SDOperand Ch = LD->getChain();
+ SDOperand Ptr = LD->getBasePtr();
+ const Value *SV = LD->getSrcValue();
+ int SVOffset = LD->getSrcValueOffset();
+ unsigned Alignment = LD->getAlignment();
+ bool isVolatile = LD->isVolatile();
+
+ Lo = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+ unsigned IncrementSize = NewNumElts * MVT::getSizeInBits(NewEltVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
- // FIXME: This creates a bogus srcvalue!
- Hi = DAG.getVecLoad(NewNumElts, EVT, Ch, Ptr, Node->getOperand(2));
+ SVOffset += IncrementSize;
+ if (Alignment > IncrementSize)
+ Alignment = IncrementSize;
+ Hi = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(TF));
break;
}
- case ISD::VBIT_CONVERT: {
+ case ISD::BIT_CONVERT: {
// We know the result is a vector. The input may be either a vector or a
// scalar value.
- if (Op.getOperand(0).getValueType() != MVT::Vector) {
+ if (!MVT::isVector(Op.getOperand(0).getValueType())) {
// Lower to a store/load. FIXME: this could be improved probably.
SDOperand Ptr = CreateStackTemporary(Op.getOperand(0).getValueType());
SDOperand St = DAG.getStore(DAG.getEntryNode(),
Op.getOperand(0), Ptr, NULL, 0);
- MVT::ValueType EVT = cast<VTSDNode>(TypeNode)->getVT();
- St = DAG.getVecLoad(NumElements, EVT, St, Ptr, DAG.getSrcValue(0));
+ St = DAG.getLoad(NewVT, St, Ptr, NULL, 0);
SplitVectorOp(St, Lo, Hi);
} else {
// If the input is a vector type, we have to either scalarize it, pack it
// or convert it based on whether the input vector type is legal.
SDNode *InVal = Node->getOperand(0).Val;
- unsigned NumElems =
- cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
-
- // If the input is from a single element vector, scalarize the vector,
- // then treat like a scalar.
- if (NumElems == 1) {
- SDOperand Scalar = PackVectorOp(Op.getOperand(0), EVT);
- Scalar = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, Scalar,
- Op.getOperand(1), Op.getOperand(2));
- SplitVectorOp(Scalar, Lo, Hi);
- } else {
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+
+ assert(NumElems > 1);
+ {
// Split the input vector.
SplitVectorOp(Op.getOperand(0), Lo, Hi);
// Convert each of the pieces now.
- Lo = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, Lo,
- NewNumEltsNode, TypeNode);
- Hi = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, Hi,
- NewNumEltsNode, TypeNode);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NewVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NewVT, Hi);
}
break;
}
}
-/// PackVectorOp - Given an operand of MVT::Vector type, convert it into the
-/// equivalent operation that returns a scalar (e.g. F32) or packed value
-/// (e.g. MVT::V4F32). When this is called, we know that PackedVT is the right
-/// type for the result.
-SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op,
- MVT::ValueType NewVT) {
- assert(Op.getValueType() == MVT::Vector && "Bad PackVectorOp invocation!");
+/// ScalarizeVectorOp - Given an operand of single-element vector type
+/// (e.g. v1f32), convert it into the equivalent operation that returns a
+/// scalar (e.g. f32) value.
+SDOperand SelectionDAGLegalize::ScalarizeVectorOp(SDOperand Op) {
+ assert(MVT::isVector(Op.getValueType()) &&
+ "Bad ScalarizeVectorOp invocation!");
SDNode *Node = Op.Val;
+ MVT::ValueType NewVT = MVT::getVectorElementType(Op.getValueType());
+ assert(MVT::getVectorNumElements(Op.getValueType()) == 1);
- // See if we already packed it.
- std::map<SDOperand, SDOperand>::iterator I = PackedNodes.find(Op);
- if (I != PackedNodes.end()) return I->second;
+ // See if we already scalarized it.
+ std::map<SDOperand, SDOperand>::iterator I = ScalarizedNodes.find(Op);
+ if (I != ScalarizedNodes.end()) return I->second;
SDOperand Result;
switch (Node->getOpcode()) {
default:
#ifndef NDEBUG
- Node->dump(); cerr << "\n";
+ Node->dump(&DAG); cerr << "\n";
#endif
- assert(0 && "Unknown vector operation in PackVectorOp!");
- case ISD::VADD:
- case ISD::VSUB:
- case ISD::VMUL:
- case ISD::VSDIV:
- case ISD::VUDIV:
- case ISD::VAND:
- case ISD::VOR:
- case ISD::VXOR:
- Result = DAG.getNode(getScalarizedOpcode(Node->getOpcode(), NewVT),
+ assert(0 && "Unknown vector operation in ScalarizeVectorOp!");
+ case ISD::ADD:
+ case ISD::FADD:
+ case ISD::SUB:
+ case ISD::FSUB:
+ case ISD::MUL:
+ case ISD::FMUL:
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::FDIV:
+ case ISD::SREM:
+ case ISD::UREM:
+ case ISD::FREM:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR:
+ Result = DAG.getNode(Node->getOpcode(),
NewVT,
- PackVectorOp(Node->getOperand(0), NewVT),
- PackVectorOp(Node->getOperand(1), NewVT));
+ ScalarizeVectorOp(Node->getOperand(0)),
+ ScalarizeVectorOp(Node->getOperand(1)));
break;
- case ISD::VLOAD: {
- SDOperand Ch = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
- SDOperand Ptr = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
-
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Node->getOperand(2));
- Result = DAG.getLoad(NewVT, Ch, Ptr, SV->getValue(), SV->getOffset());
+ case ISD::FNEG:
+ case ISD::FABS:
+ case ISD::FSQRT:
+ case ISD::FSIN:
+ case ISD::FCOS:
+ Result = DAG.getNode(Node->getOpcode(),
+ NewVT,
+ ScalarizeVectorOp(Node->getOperand(0)));
+ break;
+ case ISD::LOAD: {
+ LoadSDNode *LD = cast<LoadSDNode>(Node);
+ SDOperand Ch = LegalizeOp(LD->getChain()); // Legalize the chain.
+ SDOperand Ptr = LegalizeOp(LD->getBasePtr()); // Legalize the pointer.
+ const Value *SV = LD->getSrcValue();
+ int SVOffset = LD->getSrcValueOffset();
+ Result = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset,
+ LD->isVolatile(), LD->getAlignment());
+
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
break;
}
- case ISD::VBUILD_VECTOR:
- if (Node->getOperand(0).getValueType() == NewVT) {
- // Returning a scalar?
- Result = Node->getOperand(0);
- } else {
- // Returning a BUILD_VECTOR?
-
- // If all elements of the build_vector are undefs, return an undef.
- bool AllUndef = true;
- for (unsigned i = 0, e = Node->getNumOperands()-2; i != e; ++i)
- if (Node->getOperand(i).getOpcode() != ISD::UNDEF) {
- AllUndef = false;
- break;
- }
- if (AllUndef) {
- Result = DAG.getNode(ISD::UNDEF, NewVT);
- } else {
- Result = DAG.getNode(ISD::BUILD_VECTOR, NewVT, Node->op_begin(),
- Node->getNumOperands()-2);
- }
- }
+ case ISD::BUILD_VECTOR:
+ Result = Node->getOperand(0);
break;
- case ISD::VINSERT_VECTOR_ELT:
- if (!MVT::isVector(NewVT)) {
- // Returning a scalar? Must be the inserted element.
- Result = Node->getOperand(1);
- } else {
- Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT,
- PackVectorOp(Node->getOperand(0), NewVT),
- Node->getOperand(1), Node->getOperand(2));
- }
+ case ISD::INSERT_VECTOR_ELT:
+ // Returning the inserted scalar element.
+ Result = Node->getOperand(1);
+ break;
+ case ISD::CONCAT_VECTORS:
+ assert(Node->getOperand(0).getValueType() == NewVT &&
+ "Concat of non-legal vectors not yet supported!");
+ Result = Node->getOperand(0);
+ break;
+ case ISD::VECTOR_SHUFFLE: {
+ // Figure out if the scalar is the LHS or RHS and return it.
+ SDOperand EltNum = Node->getOperand(2).getOperand(0);
+ if (cast<ConstantSDNode>(EltNum)->getValue())
+ Result = ScalarizeVectorOp(Node->getOperand(1));
+ else
+ Result = ScalarizeVectorOp(Node->getOperand(0));
break;
- case ISD::VVECTOR_SHUFFLE:
- if (!MVT::isVector(NewVT)) {
- // Returning a scalar? Figure out if it is the LHS or RHS and return it.
- SDOperand EltNum = Node->getOperand(2).getOperand(0);
- if (cast<ConstantSDNode>(EltNum)->getValue())
- Result = PackVectorOp(Node->getOperand(1), NewVT);
- else
- Result = PackVectorOp(Node->getOperand(0), NewVT);
- } else {
- // Otherwise, return a VECTOR_SHUFFLE node. First convert the index
- // vector from a VBUILD_VECTOR to a BUILD_VECTOR.
- std::vector<SDOperand> BuildVecIdx(Node->getOperand(2).Val->op_begin(),
- Node->getOperand(2).Val->op_end()-2);
- MVT::ValueType BVT = MVT::getIntVectorWithNumElements(BuildVecIdx.size());
- SDOperand BV = DAG.getNode(ISD::BUILD_VECTOR, BVT,
- Node->getOperand(2).Val->op_begin(),
- Node->getOperand(2).Val->getNumOperands()-2);
-
- Result = DAG.getNode(ISD::VECTOR_SHUFFLE, NewVT,
- PackVectorOp(Node->getOperand(0), NewVT),
- PackVectorOp(Node->getOperand(1), NewVT), BV);
- }
+ }
+ case ISD::EXTRACT_SUBVECTOR:
+ Result = Node->getOperand(0);
+ assert(Result.getValueType() == NewVT);
break;
- case ISD::VBIT_CONVERT:
- if (Op.getOperand(0).getValueType() != MVT::Vector)
- Result = DAG.getNode(ISD::BIT_CONVERT, NewVT, Op.getOperand(0));
- else {
- // If the input is a vector type, we have to either scalarize it, pack it
- // or convert it based on whether the input vector type is legal.
- SDNode *InVal = Node->getOperand(0).Val;
- unsigned NumElems =
- cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
- MVT::ValueType EVT = cast<VTSDNode>(*(InVal->op_end()-1))->getVT();
-
- // Figure out if there is a Packed type corresponding to this Vector
- // type. If so, convert to the vector type.
- MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) {
- // Turn this into a bit convert of the packed input.
- Result = DAG.getNode(ISD::BIT_CONVERT, NewVT,
- PackVectorOp(Node->getOperand(0), TVT));
- break;
- } else if (NumElems == 1) {
- // Turn this into a bit convert of the scalar input.
- Result = DAG.getNode(ISD::BIT_CONVERT, NewVT,
- PackVectorOp(Node->getOperand(0), EVT));
- break;
- } else {
- // FIXME: UNIMP!
- assert(0 && "Cast from unsupported vector type not implemented yet!");
- }
- }
+ case ISD::BIT_CONVERT:
+ Result = DAG.getNode(ISD::BIT_CONVERT, NewVT, Op.getOperand(0));
break;
- case ISD::VSELECT:
+ case ISD::SELECT:
Result = DAG.getNode(ISD::SELECT, NewVT, Op.getOperand(0),
- PackVectorOp(Op.getOperand(1), NewVT),
- PackVectorOp(Op.getOperand(2), NewVT));
+ ScalarizeVectorOp(Op.getOperand(1)),
+ ScalarizeVectorOp(Op.getOperand(2)));
break;
}
if (TLI.isTypeLegal(NewVT))
Result = LegalizeOp(Result);
- bool isNew = PackedNodes.insert(std::make_pair(Op, Result)).second;
- assert(isNew && "Value already packed?");
+ bool isNew = ScalarizedNodes.insert(std::make_pair(Op, Result)).second;
+ assert(isNew && "Value already scalarized?");
return Result;
}