Generalize getCopyFromParts and getCopyToParts to
handle arbitrary precision integers and any number
of parts. For example, on a 32 bit machine an i50
corresponds to two i32 parts. getCopyToParts will
extend the i50 to an i64 then write half of the i64
to each part; getCopyFromParts will combine the two
i32 parts into an i64 then truncate the result to
i50.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47024 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 65dea71..76e8d28 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -633,100 +633,136 @@
MVT::ValueType ValueVT,
ISD::NodeType AssertOp = ISD::DELETED_NODE,
bool TruncExact = false) {
- if (!MVT::isVector(ValueVT) || NumParts == 1) {
- SDOperand Val = Parts[0];
+ assert(NumParts > 0 && "No parts to assemble!");
+ TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ SDOperand Val = Parts[0];
- // If the value was expanded, copy from the top part.
- if (NumParts > 1) {
- assert(NumParts == 2 &&
- "Cannot expand to more than 2 elts yet!");
- SDOperand Hi = Parts[1];
- if (!DAG.getTargetLoweringInfo().isLittleEndian())
- std::swap(Val, Hi);
- return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi);
- }
+ if (NumParts > 1) {
+ // Assemble the value from multiple parts.
+ if (!MVT::isVector(ValueVT)) {
+ unsigned PartBits = MVT::getSizeInBits(PartVT);
+ unsigned ValueBits = MVT::getSizeInBits(ValueVT);
- // Otherwise, if the value was promoted or extended, truncate it to the
- // appropriate type.
- if (PartVT == ValueVT)
- return Val;
-
- if (MVT::isVector(PartVT)) {
- assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
- return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
- }
-
- if (MVT::isVector(ValueVT)) {
- assert(NumParts == 1 &&
- MVT::getVectorElementType(ValueVT) == PartVT &&
- MVT::getVectorNumElements(ValueVT) == 1 &&
- "Only trivial scalar-to-vector conversions should get here!");
- return DAG.getNode(ISD::BUILD_VECTOR, ValueVT, Val);
- }
-
- if (MVT::isInteger(PartVT) &&
- MVT::isInteger(ValueVT)) {
- if (ValueVT < PartVT) {
- // For a truncate, see if we have any information to
- // indicate whether the truncated bits will always be
- // zero or sign-extension.
- if (AssertOp != ISD::DELETED_NODE)
- Val = DAG.getNode(AssertOp, PartVT, Val,
- DAG.getValueType(ValueVT));
- return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ // Assemble the power of 2 part.
+ unsigned RoundParts = NumParts & (NumParts - 1) ?
+ 1 << Log2_32(NumParts) : NumParts;
+ unsigned RoundBits = PartBits * RoundParts;
+ MVT::ValueType RoundVT = RoundBits == ValueBits ?
+ ValueVT : MVT::getIntegerType(RoundBits);
+ SDOperand Lo, Hi;
+
+ if (RoundParts > 2) {
+ MVT::ValueType HalfVT = MVT::getIntegerType(RoundBits/2);
+ Lo = getCopyFromParts(DAG, Parts, RoundParts/2, PartVT, HalfVT);
+ Hi = getCopyFromParts(DAG, Parts+RoundParts/2, RoundParts/2,
+ PartVT, HalfVT);
} else {
- return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
+ Lo = Parts[0];
+ Hi = Parts[1];
}
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Val = DAG.getNode(ISD::BUILD_PAIR, RoundVT, Lo, Hi);
+
+ if (RoundParts < NumParts) {
+ // Assemble the trailing non-power-of-2 part.
+ unsigned OddParts = NumParts - RoundParts;
+ MVT::ValueType OddVT = MVT::getIntegerType(OddParts * PartBits);
+ Hi = getCopyFromParts(DAG, Parts+RoundParts, OddParts, PartVT, OddVT);
+
+ // Combine the round and odd parts.
+ Lo = Val;
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ MVT::ValueType TotalVT = MVT::getIntegerType(NumParts * PartBits);
+ Hi = DAG.getNode(ISD::ANY_EXTEND, TotalVT, Hi);
+ Hi = DAG.getNode(ISD::SHL, TotalVT, Hi,
+ DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()),
+ TLI.getShiftAmountTy()));
+ Lo = DAG.getNode(ISD::ZERO_EXTEND, TotalVT, Lo);
+ Val = DAG.getNode(ISD::OR, TotalVT, Lo, Hi);
+ }
+ } else {
+ // Handle a multi-element vector.
+ MVT::ValueType IntermediateVT, RegisterVT;
+ unsigned NumIntermediates;
+ unsigned NumRegs =
+ TLI.getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
+ RegisterVT);
+
+ assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
+ assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+ assert(RegisterVT == Parts[0].getValueType() &&
+ "Part type doesn't match part!");
+
+ // Assemble the parts into intermediate operands.
+ SmallVector<SDOperand, 8> Ops(NumIntermediates);
+ if (NumIntermediates == NumParts) {
+ // If the register was not expanded, truncate or copy the value,
+ // as appropriate.
+ for (unsigned i = 0; i != NumParts; ++i)
+ Ops[i] = getCopyFromParts(DAG, &Parts[i], 1,
+ PartVT, IntermediateVT);
+ } else if (NumParts > 0) {
+ // If the intermediate type was expanded, build the intermediate operands
+ // from the parts.
+ assert(NumParts % NumIntermediates == 0 &&
+ "Must expand into a divisible number of parts!");
+ unsigned Factor = NumParts / NumIntermediates;
+ for (unsigned i = 0; i != NumIntermediates; ++i)
+ Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
+ PartVT, IntermediateVT);
+ }
+
+ // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
+ // operands.
+ Val = DAG.getNode(MVT::isVector(IntermediateVT) ?
+ ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR,
+ ValueVT, &Ops[0], NumIntermediates);
}
-
- if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT))
- return DAG.getNode(ISD::FP_ROUND, ValueVT, Val,
- DAG.getIntPtrConstant(TruncExact));
-
- if (MVT::getSizeInBits(PartVT) == MVT::getSizeInBits(ValueVT))
- return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
-
- assert(0 && "Unknown mismatch!");
}
- // Handle a multi-element vector.
- MVT::ValueType IntermediateVT, RegisterVT;
- unsigned NumIntermediates;
- unsigned NumRegs =
- DAG.getTargetLoweringInfo()
- .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
- RegisterVT);
+ // There is now one part, held in Val. Correct it to match ValueVT.
+ PartVT = Val.getValueType();
- assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
- assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
- assert(RegisterVT == Parts[0].getValueType() &&
- "Part type doesn't match part!");
+ if (PartVT == ValueVT)
+ return Val;
- // Assemble the parts into intermediate operands.
- SmallVector<SDOperand, 8> Ops(NumIntermediates);
- if (NumIntermediates == NumParts) {
- // If the register was not expanded, truncate or copy the value,
- // as appropriate.
- for (unsigned i = 0; i != NumParts; ++i)
- Ops[i] = getCopyFromParts(DAG, &Parts[i], 1,
- PartVT, IntermediateVT);
- } else if (NumParts > 0) {
- // If the intermediate type was expanded, build the intermediate operands
- // from the parts.
- assert(NumParts % NumIntermediates == 0 &&
- "Must expand into a divisible number of parts!");
- unsigned Factor = NumParts / NumIntermediates;
- for (unsigned i = 0; i != NumIntermediates; ++i)
- Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
- PartVT, IntermediateVT);
+ if (MVT::isVector(PartVT)) {
+ assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
+ return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
}
-
- // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
- // operands.
- return DAG.getNode(MVT::isVector(IntermediateVT) ?
- ISD::CONCAT_VECTORS :
- ISD::BUILD_VECTOR,
- ValueVT, &Ops[0], NumIntermediates);
+
+ if (MVT::isVector(ValueVT)) {
+ assert(MVT::getVectorElementType(ValueVT) == PartVT &&
+ MVT::getVectorNumElements(ValueVT) == 1 &&
+ "Only trivial scalar-to-vector conversions should get here!");
+ return DAG.getNode(ISD::BUILD_VECTOR, ValueVT, Val);
+ }
+
+ if (MVT::isInteger(PartVT) &&
+ MVT::isInteger(ValueVT)) {
+ if (MVT::getSizeInBits(ValueVT) < MVT::getSizeInBits(PartVT)) {
+ // For a truncate, see if we have any information to
+ // indicate whether the truncated bits will always be
+ // zero or sign-extension.
+ if (AssertOp != ISD::DELETED_NODE)
+ Val = DAG.getNode(AssertOp, PartVT, Val,
+ DAG.getValueType(ValueVT));
+ return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ } else {
+ return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
+ }
+ }
+
+ if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT))
+ return DAG.getNode(ISD::FP_ROUND, ValueVT, Val,
+ DAG.getIntPtrConstant(TruncExact));
+
+ if (MVT::getSizeInBits(PartVT) == MVT::getSizeInBits(ValueVT))
+ return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
+
+ assert(0 && "Unknown mismatch!");
}
/// getCopyToParts - Create a series of nodes that contain the specified value
@@ -741,47 +777,113 @@
TargetLowering &TLI = DAG.getTargetLoweringInfo();
MVT::ValueType PtrVT = TLI.getPointerTy();
MVT::ValueType ValueVT = Val.getValueType();
+ unsigned PartBits = MVT::getSizeInBits(PartVT);
+ assert(TLI.isTypeLegal(PartVT) && "Copying to an illegal type!");
- if (!MVT::isVector(ValueVT) || NumParts == 1) {
- // If the value was expanded, copy from the parts.
- if (NumParts > 1) {
- for (unsigned i = 0; i != NumParts; ++i)
- Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val,
- DAG.getConstant(i, PtrVT));
- if (!DAG.getTargetLoweringInfo().isLittleEndian())
- std::reverse(Parts, Parts + NumParts);
+ if (!NumParts)
+ return;
+
+ if (!MVT::isVector(ValueVT)) {
+ if (PartVT == ValueVT) {
+ assert(NumParts == 1 && "No-op copy with multiple parts!");
+ Parts[0] = Val;
return;
}
- // If there is a single part and the types differ, this must be
- // a promotion.
- if (PartVT != ValueVT) {
- if (MVT::isVector(PartVT)) {
- assert(MVT::isVector(ValueVT) &&
- "Not a vector-vector cast?");
- Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
- } else if (MVT::isVector(ValueVT)) {
- assert(NumParts == 1 &&
- MVT::getVectorElementType(ValueVT) == PartVT &&
- MVT::getVectorNumElements(ValueVT) == 1 &&
- "Only trivial vector-to-scalar conversions should get here!");
- Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, PartVT, Val,
- DAG.getConstant(0, PtrVT));
- } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
- if (PartVT < ValueVT)
- Val = DAG.getNode(ISD::TRUNCATE, PartVT, Val);
- else
- Val = DAG.getNode(ExtendKind, PartVT, Val);
- } else if (MVT::isFloatingPoint(PartVT) &&
- MVT::isFloatingPoint(ValueVT)) {
+ if (NumParts * PartBits > MVT::getSizeInBits(ValueVT)) {
+ // If the parts cover more bits than the value has, promote the value.
+ if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT)) {
+ assert(NumParts == 1 && "Do not know what to promote to!");
Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
- } else if (MVT::getSizeInBits(PartVT) ==
- MVT::getSizeInBits(ValueVT)) {
- Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+ } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ExtendKind, ValueVT, Val);
+ } else {
+ assert(0 && "Unknown mismatch!");
+ }
+ } else if (PartBits == MVT::getSizeInBits(ValueVT)) {
+ // Different types of the same size.
+ assert(NumParts == 1 && PartVT != ValueVT);
+ Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+ } else if (NumParts * PartBits < MVT::getSizeInBits(ValueVT)) {
+ // If the parts cover less bits than value has, truncate the value.
+ if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
} else {
assert(0 && "Unknown mismatch!");
}
}
+
+ // The value may have changed - recompute ValueVT.
+ ValueVT = Val.getValueType();
+ assert(NumParts * PartBits == MVT::getSizeInBits(ValueVT) &&
+ "Failed to tile the value with PartVT!");
+
+ if (NumParts == 1) {
+ assert(PartVT == ValueVT && "Type conversion failed!");
+ Parts[0] = Val;
+ return;
+ }
+
+ // Expand the value into multiple parts.
+ if (NumParts & (NumParts - 1)) {
+ // The number of parts is not a power of 2. Split off and copy the tail.
+ assert(MVT::isInteger(PartVT) && MVT::isInteger(ValueVT) &&
+ "Do not know what to expand to!");
+ unsigned RoundParts = 1 << Log2_32(NumParts);
+ unsigned RoundBits = RoundParts * PartBits;
+ unsigned OddParts = NumParts - RoundParts;
+ SDOperand OddVal = DAG.getNode(ISD::SRL, ValueVT, Val,
+ DAG.getConstant(RoundBits,
+ TLI.getShiftAmountTy()));
+ getCopyToParts(DAG, OddVal, Parts + RoundParts, OddParts, PartVT);
+ if (TLI.isBigEndian())
+ // The odd parts were reversed by getCopyToParts - unreverse them.
+ std::reverse(Parts + RoundParts, Parts + NumParts);
+ NumParts = RoundParts;
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ }
+
+ // The number of parts is a power of 2. Repeatedly bisect the value using
+ // EXTRACT_ELEMENT.
+ Parts[0] = Val;
+ for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) {
+ for (unsigned i = 0; i < NumParts; i += StepSize) {
+ unsigned ThisBits = StepSize * PartBits / 2;
+ MVT::ValueType ThisVT =
+ ThisBits == PartBits ? PartVT : MVT::getIntegerType (ThisBits);
+
+ Parts[i+StepSize/2] =
+ DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Parts[i],
+ DAG.getConstant(1, PtrVT));
+ Parts[i] =
+ DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Parts[i],
+ DAG.getConstant(0, PtrVT));
+ }
+ }
+
+ if (TLI.isBigEndian())
+ std::reverse(Parts, Parts + NumParts);
+
+ return;
+ }
+
+ // Vector ValueVT.
+ if (NumParts == 1) {
+ if (PartVT != ValueVT) {
+ if (MVT::isVector(PartVT)) {
+ Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+ } else {
+ assert(MVT::getVectorElementType(ValueVT) == PartVT &&
+ MVT::getVectorNumElements(ValueVT) == 1 &&
+ "Only trivial vector-to-scalar conversions should get here!");
+ Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, PartVT, Val,
+ DAG.getConstant(0, PtrVT));
+ }
+ }
+
Parts[0] = Val;
return;
}