unsigned NumResults = N->getNumValues();
do {
MVT::ValueType ResultVT = N->getValueType(i);
- LegalizeAction Action = getTypeAction(ResultVT);
- if (Action == Promote) {
+ switch (getTypeAction(ResultVT)) {
+ default:
+ assert(false && "Unknown action!");
+ case Legal:
+ break;
+ case Promote:
PromoteResult(N, i);
goto NodeDone;
- } else if (Action == Expand) {
- // Expand can mean 1) split integer in half 2) scalarize single-element
- // vector 3) split vector in half.
- if (!MVT::isVector(ResultVT))
- ExpandResult(N, i);
- else if (MVT::getVectorNumElements(ResultVT) == 1)
- ScalarizeResult(N, i); // Scalarize the single-element vector.
- else
- SplitResult(N, i); // Split the vector in half.
+ case Expand:
+ ExpandResult(N, i);
+ goto NodeDone;
+ case Scalarize:
+ ScalarizeResult(N, i);
+ goto NodeDone;
+ case Split:
+ SplitResult(N, i);
goto NodeDone;
- } else {
- assert(Action == Legal && "Unknown action!");
}
} while (++i < NumResults);
-
+
// Scan the operand list for the node, handling any nodes with operands that
// are illegal.
{
bool NeedsRevisit = false;
for (i = 0; i != NumOperands; ++i) {
MVT::ValueType OpVT = N->getOperand(i).getValueType();
- LegalizeAction Action = getTypeAction(OpVT);
- if (Action == Promote) {
+ switch (getTypeAction(OpVT)) {
+ default:
+ assert(false && "Unknown action!");
+ case Legal:
+ continue;
+ case Promote:
NeedsRevisit = PromoteOperand(N, i);
break;
- } else if (Action == Expand) {
- // Expand can mean 1) split integer in half 2) scalarize single-element
- // vector 3) split vector in half.
- if (!MVT::isVector(OpVT)) {
- NeedsRevisit = ExpandOperand(N, i);
- } else if (MVT::getVectorNumElements(OpVT) == 1) {
- // Scalarize the single-element vector.
- NeedsRevisit = ScalarizeOperand(N, i);
- } else {
- NeedsRevisit = SplitOperand(N, i); // Split the vector in half.
- }
+ case Expand:
+ NeedsRevisit = ExpandOperand(N, i);
+ break;
+ case Scalarize:
+ NeedsRevisit = ScalarizeOperand(N, i);
+ break;
+ case Split:
+ NeedsRevisit = SplitOperand(N, i);
break;
- } else {
- assert(Action == Legal && "Unknown action!");
}
+ break;
}
// If the node needs revisiting, don't add all users to the worklist etc.
case Legal: break;
case Promote: Op2 = GetPromotedOp(Op2); break;
}
-
+
// The length could have any action required.
SDOperand Length = N->getOperand(3);
switch (getTypeAction(Length.getValueType())) {
GetExpandedOp(Length, Length, Dummy);
break;
}
-
+
SDOperand Align = N->getOperand(4);
switch (getTypeAction(Align.getValueType())) {
default: assert(0 && "Unknown action for memop operand");
case Legal: break;
case Promote: Align = GetPromotedZExtOp(Align); break;
}
-
+
SDOperand AlwaysInline = N->getOperand(5);
switch (getTypeAction(AlwaysInline.getValueType())) {
default: assert(0 && "Unknown action for memop operand");
case Legal: break;
case Promote: AlwaysInline = GetPromotedZExtOp(AlwaysInline); break;
}
-
+
SDOperand Ops[] = { Chain, Ptr, Op2, Length, Align, AlwaysInline };
return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
}
enum LegalizeAction {
Legal, // The target natively supports this type.
Promote, // This type should be executed in a larger type.
- Expand // This type should be split into two types of half the size.
+ Expand, // This type should be split into two types of half the size.
+ Scalarize, // Replace this one-element vector type with its element type.
+ Split // This vector type should be split into smaller vectors.
};
-
+
/// ValueTypeActions - This is a bitvector that contains two bits for each
/// simple value type, where the two bits correspond to the LegalizeAction
- /// enum. This can be queried with "getTypeAction(VT)".
+ /// enum from TargetLowering. This can be queried with "getTypeAction(VT)".
TargetLowering::ValueTypeActionImpl ValueTypeActions;
/// getTypeAction - Return how we should legalize values of this type, either
- /// it is already legal or we need to expand it into multiple registers of
- /// smaller integer type, or we need to promote it to a larger type.
+ /// it is already legal, or we need to promote it to a larger integer type, or
+ /// we need to expand it into multiple registers of a smaller integer type, or
+ /// we need to scalarize a one-element vector type into the element type, or
+ /// we need to split a vector type into smaller vector types.
LegalizeAction getTypeAction(MVT::ValueType VT) const {
- return (LegalizeAction)ValueTypeActions.getTypeAction(VT);
+ switch (ValueTypeActions.getTypeAction(VT)) {
+ default:
+ assert(false && "Unknown legalize action!");
+ case TargetLowering::Legal:
+ return Legal;
+ case TargetLowering::Promote:
+ return Promote;
+ case TargetLowering::Expand:
+ // Expand can mean 1) split integer in half 2) scalarize single-element
+ // vector 3) split vector in two.
+ if (!MVT::isVector(VT))
+ return Expand;
+ else if (MVT::getVectorNumElements(VT) == 1)
+ return Scalarize;
+ else
+ return Split;
+ }
}
-
+
/// isTypeLegal - Return true if this type is legal on this target.
- ///
bool isTypeLegal(MVT::ValueType VT) const {
- return getTypeAction(VT) == Legal;
+ return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal;
}
-
+
/// PromotedNodes - For nodes that are below legal width, this map indicates
/// what promoted value to use.
DenseMap<SDOperand, SDOperand> PromotedNodes;
// Result Promotion.
void PromoteResult(SDNode *N, unsigned ResNo);
+ SDOperand PromoteResult_BIT_CONVERT(SDNode *N);
SDOperand PromoteResult_BUILD_PAIR(SDNode *N);
SDOperand PromoteResult_Constant(SDNode *N);
SDOperand PromoteResult_CTLZ(SDNode *N);
SDOperand PromoteResult_CTPOP(SDNode *N);
SDOperand PromoteResult_CTTZ(SDNode *N);
+ SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand PromoteResult_FP_ROUND(SDNode *N);
SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
SDOperand PromoteResult_INT_EXTEND(SDNode *N);
void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
// Operand Vector Scalarization: <1 x ty> -> ty.
bool ScalarizeOperand(SDNode *N, unsigned OpNo);
+ SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N);
SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo);
// Operand Vector Scalarization: <128 x ty> -> 2 x <64 x ty>.
bool SplitOperand(SDNode *N, unsigned OpNo);
+ SDOperand SplitOp_BIT_CONVERT(SDNode *N);
SDOperand SplitOp_EXTRACT_SUBVECTOR(SDNode *N);
+ SDOperand SplitOp_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand SplitOp_RET(SDNode *N, unsigned OpNo);
SDOperand SplitOp_STORE(StoreSDNode *N, unsigned OpNo);
SDOperand SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo);
case ISD::CTLZ: ExpandResult_CTLZ(N, Lo, Hi); break;
case ISD::CTPOP: ExpandResult_CTPOP(N, Lo, Hi); break;
case ISD::CTTZ: ExpandResult_CTTZ(N, Lo, Hi); break;
+
+ case ISD::EXTRACT_VECTOR_ELT:
+ ExpandResult_EXTRACT_VECTOR_ELT(N, Lo, Hi);
+ break;
}
// If Lo/Hi is null, the sub-method took care of registering results etc.
// For example, extension of an i48 to an i64. The operand type necessarily
// promotes to the result type, so will end up being expanded too.
assert(getTypeAction(Op.getValueType()) == Promote &&
- "Don't know how to expand this result!");
+ "Only know how to promote this result!");
SDOperand Res = GetPromotedOp(Op);
assert(Res.getValueType() == N->getValueType(0) &&
"Operand over promoted?");
// For example, extension of an i48 to an i64. The operand type necessarily
// promotes to the result type, so will end up being expanded too.
assert(getTypeAction(Op.getValueType()) == Promote &&
- "Don't know how to expand this result!");
+ "Only know how to promote this result!");
SDOperand Res = GetPromotedOp(Op);
assert(Res.getValueType() == N->getValueType(0) &&
"Operand over promoted?");
// For example, extension of an i48 to an i64. The operand type necessarily
// promotes to the result type, so will end up being expanded too.
assert(getTypeAction(Op.getValueType()) == Promote &&
- "Don't know how to expand this result!");
+ "Only know how to promote this result!");
SDOperand Res = GetPromotedOp(Op);
assert(Res.getValueType() == N->getValueType(0) &&
"Operand over promoted?");
void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
// Lower the bit-convert to a store/load from the stack, then expand the load.
+ // TODO: If the operand also needs expansion then this could be turned into
+ // conversion of the expanded pieces. But there needs to be a testcase first!
SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
ExpandResult_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
}
Hi = DAG.getConstant(0, NVT);
}
+void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N,
+ SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand OldVec = N->getOperand(0);
+ unsigned OldElts = MVT::getVectorNumElements(OldVec.getValueType());
+
+ // Convert to a vector of the expanded element type, for example
+ // <2 x i64> -> <4 x i32>.
+ MVT::ValueType OldVT = N->getValueType(0);
+ MVT::ValueType NewVT = TLI.getTypeToTransformTo(OldVT);
+ assert(MVT::getSizeInBits(OldVT) == 2 * MVT::getSizeInBits(NewVT) &&
+ "Do not know how to handle this expansion!");
+
+ SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getVectorType(NewVT, 2 * OldElts),
+ OldVec);
+
+ // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector.
+ SDOperand Idx = N->getOperand(1);
+
+ // Make sure the type of Idx is big enough to hold the new values.
+ if (MVT::getSizeInBits(Idx.getValueType()) < 32)
+ Idx = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Idx);
+
+ Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
+ Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
+
+ Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
+ DAG.getConstant(1, Idx.getValueType()));
+ Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+}
+
/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded,
/// and the shift amount is a constant 'Amt'. Expand the operation.
void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
}
SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) {
+ if (MVT::isVector(N->getValueType(0))) {
+ // An illegal integer type is being converted to a legal vector type.
+ // Make a two element vector out of the expanded parts and convert that
+ // instead, but only if the new vector type is legal (otherwise there
+ // is no point, and it might create expansion loops). For example, on
+ // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32.
+ MVT::ValueType OVT = N->getOperand(0).getValueType();
+ MVT::ValueType NVT = MVT::getVectorType(TLI.getTypeToTransformTo(OVT), 2);
+
+ if (isTypeLegal(NVT)) {
+ SDOperand Parts[2];
+ GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]);
+
+ if (TLI.isBigEndian())
+ std::swap(Parts[0], Parts[1]);
+
+ SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2);
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec);
+ }
+ }
+
+ // Otherwise, store to a temporary and load out again as the new type.
return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
}
case ISD::SETCC: Result = PromoteResult_SETCC(N); break;
case ISD::LOAD: Result = PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break;
+ case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break;
case ISD::AND:
case ISD::OR:
case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break;
case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break;
case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break;
+
+ case ISD::EXTRACT_VECTOR_ELT:
+ Result = PromoteResult_EXTRACT_VECTOR_ELT(N);
+ break;
}
-
+
// If Result is null, the sub-method took care of registering the result.
if (Result.Val)
SetPromotedOp(SDOperand(N, ResNo), Result);
return DAG.getNode(ISD::OR, NVT, Lo, Hi);
}
+SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
+ SDOperand InOp = N->getOperand(0);
+ MVT::ValueType InVT = InOp.getValueType();
+ MVT::ValueType NInVT = TLI.getTypeToTransformTo(InVT);
+ MVT::ValueType OutVT = TLI.getTypeToTransformTo(N->getValueType(0));
+
+ switch (getTypeAction(InVT)) {
+ default:
+ assert(false && "Unknown type action!");
+ break;
+ case Legal:
+ break;
+ case Promote:
+ if (MVT::getSizeInBits(OutVT) == MVT::getSizeInBits(NInVT))
+ // The input promotes to the same size. Convert the promoted value.
+ return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp));
+ break;
+ case Expand:
+ break;
+ case Scalarize:
+ // Convert the element to an integer and promote it by hand.
+ InOp = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getIntegerType(MVT::getSizeInBits(InVT)),
+ GetScalarizedOp(InOp));
+ InOp = DAG.getNode(ISD::ANY_EXTEND,
+ MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp);
+ return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
+ case Split:
+ // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split
+ // pieces of the input into integers and reassemble in the final type.
+ SDOperand Lo, Hi;
+ GetSplitOp(N->getOperand(0), Lo, Hi);
+
+ unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
+ Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo);
+
+ unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
+ Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ MVT::ValueType TargetTy = MVT::getIntegerType(MVT::getSizeInBits(OutVT));
+ Hi = DAG.getNode(ISD::ANY_EXTEND, TargetTy, Hi);
+ Hi = DAG.getNode(ISD::SHL, TargetTy, Hi,
+ DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()),
+ TLI.getShiftAmountTy()));
+ Lo = DAG.getNode(ISD::ZERO_EXTEND, TargetTy, Lo);
+
+ return DAG.getNode(ISD::BIT_CONVERT, OutVT,
+ DAG.getNode(ISD::OR, TargetTy, Lo, Hi));
+ }
+
+ // Otherwise, lower the bit-convert to a store/load from the stack, then
+ // promote the load.
+ SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
+ return PromoteResult_LOAD(cast<LoadSDNode>(Op.Val));
+}
+
SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
// The input may have strange things in the top bits of the registers, but
// these operations don't care. They may have weird bits going out, but
return DAG.getNode(ISD::CTTZ, NVT, Op);
}
+SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) {
+ MVT::ValueType OldVT = N->getValueType(0);
+ SDOperand OldVec = N->getOperand(0);
+ unsigned OldElts = MVT::getVectorNumElements(OldVec.getValueType());
+
+ if (OldElts == 1) {
+ assert(!isTypeLegal(OldVec.getValueType()) &&
+ "Legal one-element vector of a type needing promotion!");
+ // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp,
+ // but this would be wrong because the scalarized value may not yet have
+ // been processed.
+ return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT),
+ GetScalarizedOp(OldVec));
+ }
+
+ // Convert to a vector half as long with an element type of twice the width,
+ // for example <4 x i16> -> <2 x i32>.
+ assert(!(OldElts & 1) && "Odd length vectors not supported!");
+ MVT::ValueType NewVT = MVT::getIntegerType(2 * MVT::getSizeInBits(OldVT));
+ assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT));
+
+ SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getVectorType(NewVT, OldElts / 2),
+ OldVec);
+
+ // Extract the element at OldIdx / 2 from the new vector.
+ SDOperand OldIdx = N->getOperand(1);
+ SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx,
+ DAG.getConstant(1, TLI.getShiftAmountTy()));
+ SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx);
+
+ // Select the appropriate half of the element: Lo if OldIdx was even,
+ // Hi if it was odd.
+ SDOperand Lo = Elt;
+ SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
+ DAG.getConstant(MVT::getSizeInBits(OldVT),
+ TLI.getShiftAmountTy()));
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx,
+ DAG.getConstant(1, TLI.getShiftAmountTy()));
+ return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
+}
+
//===----------------------------------------------------------------------===//
// Operand Promotion
//===----------------------------------------------------------------------===//
assert(0 && "Do not know how to scalarize this operator's operand!");
abort();
+ case ISD::BIT_CONVERT:
+ Res = ScalarizeOp_BIT_CONVERT(N); break;
+
case ISD::EXTRACT_VECTOR_ELT:
Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
return false;
}
+/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
+/// to be scalarized, it must be <1 x ty>. Convert the element instead.
+SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
+ SDOperand Elt = GetScalarizedOp(N->getOperand(0));
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
+}
+
/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
/// scalarized, it must be <1 x ty>, so just return the element, ignoring the
/// index.
else
Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, ScalarOp,
DAG.getConstant(Index - LoNumElts, TLI.getPointerTy()));
-
}
void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
// We know the result is a vector. The input may be either a vector or a
// scalar value.
+ MVT::ValueType LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+
SDOperand InOp = N->getOperand(0);
- if (MVT::isVector(InOp.getValueType()) &&
- MVT::getVectorNumElements(InOp.getValueType()) != 1) {
- // If this is a vector, split the vector and convert each of the pieces now.
- GetSplitOp(InOp, Lo, Hi);
-
- MVT::ValueType LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+ MVT::ValueType InVT = InOp.getValueType();
+ MVT::ValueType NewInVT = TLI.getTypeToTransformTo(InVT);
+ switch (getTypeAction(InVT)) {
+ default:
+ assert(false && "Unknown type action!");
+ case Legal:
+ break;
+ case Promote:
+ break;
+ case Scalarize:
+ // While it is tempting to extract the scalarized operand, check whether it
+ // needs expansion, and if so process it in the Expand case below, there is
+ // no guarantee that the scalarized operand has been processed yet. If it
+ // hasn't then the call to GetExpandedOp will abort. So just give up.
+ break;
+ case Expand:
+ // A scalar to vector conversion, where the scalar needs expansion.
+ // Check that the vector is being split in two.
+ if (MVT::getSizeInBits(NewInVT) == MVT::getSizeInBits(LoVT)) {
+ // Convert each expanded piece of the scalar now.
+ GetExpandedOp(InOp, Lo, Hi);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
+ return;
+ }
+ break;
+ case Split:
+ // If the input is a vector that needs to be split, convert each split
+ // piece of the input now.
+ GetSplitOp(InOp, Lo, Hi);
Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
return;
}
-
+
// Lower the bit-convert to a store/load from the stack, then split the load.
- SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
+ SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
SplitRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
}
case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break;
case ISD::RET: Res = SplitOp_RET(N, OpNo); break;
- case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break;
- case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break;
+ case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break;
+
+ case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break;
+ case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break;
+ case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break;
}
}
return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign);
}
+SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
+ // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will
+ // end up being split all the way down to individual components. Convert the
+ // split pieces into integers and reassemble.
+ SDOperand Lo, Hi;
+ GetSplitOp(N->getOperand(0), Lo, Hi);
+
+ unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
+ Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo);
+
+ unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
+ Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ assert(LoBits == HiBits && "Do not know how to assemble odd sized vectors!");
+
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
+ DAG.getNode(ISD::BUILD_PAIR,
+ MVT::getIntegerType(LoBits+HiBits), Lo, Hi));
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {
+ SDOperand Vec = N->getOperand(0);
+ SDOperand Idx = N->getOperand(1);
+ MVT::ValueType VecVT = Vec.getValueType();
+
+ if (isa<ConstantSDNode>(Idx)) {
+ uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
+ assert(IdxVal < MVT::getVectorNumElements(VecVT) &&
+ "Invalid vector index!");
+
+ SDOperand Lo, Hi;
+ GetSplitOp(Vec, Lo, Hi);
+
+ uint64_t LoElts = MVT::getVectorNumElements(Lo.getValueType());
+
+ if (IdxVal < LoElts)
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx);
+ else
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi,
+ DAG.getConstant(IdxVal - LoElts,
+ Idx.getValueType()));
+ }
+
+ // Store the vector to the stack and load back the required element.
+ SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
+ SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
+
+ // Add the offset to the index.
+ MVT::ValueType EltVT = MVT::getVectorElementType(VecVT);
+ unsigned EltSize = MVT::getSizeInBits(EltVT)/8; // FIXME: should be ABI size.
+ Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx,
+ DAG.getConstant(EltSize, Idx.getValueType()));
+
+ if (MVT::getSizeInBits(Idx.getValueType()) >
+ MVT::getSizeInBits(TLI.getPointerTy()))
+ Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), Idx);
+ else
+ Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
+
+ StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr);
+ return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0);
+}
+
SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) {
// We know that the extracted result type is legal. For now, assume the index
// is a constant.