aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp111
1 files changed, 110 insertions, 1 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
index c4eb059380..f3232fc914 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
@@ -50,6 +50,7 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
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:
@@ -74,8 +75,12 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
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);
@@ -214,6 +219,65 @@ SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) {
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
@@ -315,6 +379,51 @@ SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) {
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
//===----------------------------------------------------------------------===//