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
This commit is contained in:
Duncan Sands 2008-02-12 20:46:31 +00:00
parent 394d28048c
commit 014e04a5da

View File

@ -633,68 +633,61 @@ static SDOperand getCopyFromParts(SelectionDAG &DAG,
MVT::ValueType ValueVT, MVT::ValueType ValueVT,
ISD::NodeType AssertOp = ISD::DELETED_NODE, ISD::NodeType AssertOp = ISD::DELETED_NODE,
bool TruncExact = false) { bool TruncExact = false) {
if (!MVT::isVector(ValueVT) || NumParts == 1) { assert(NumParts > 0 && "No parts to assemble!");
TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDOperand Val = Parts[0]; SDOperand Val = Parts[0];
// If the value was expanded, copy from the top part.
if (NumParts > 1) { if (NumParts > 1) {
assert(NumParts == 2 && // Assemble the value from multiple parts.
"Cannot expand to more than 2 elts yet!"); if (!MVT::isVector(ValueVT)) {
SDOperand Hi = Parts[1]; unsigned PartBits = MVT::getSizeInBits(PartVT);
if (!DAG.getTargetLoweringInfo().isLittleEndian()) unsigned ValueBits = MVT::getSizeInBits(ValueVT);
std::swap(Val, Hi);
return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi);
}
// Otherwise, if the value was promoted or extended, truncate it to the // Assemble the power of 2 part.
// appropriate type. unsigned RoundParts = NumParts & (NumParts - 1) ?
if (PartVT == ValueVT) 1 << Log2_32(NumParts) : NumParts;
return Val; unsigned RoundBits = PartBits * RoundParts;
MVT::ValueType RoundVT = RoundBits == ValueBits ?
ValueVT : MVT::getIntegerType(RoundBits);
SDOperand Lo, Hi;
if (MVT::isVector(PartVT)) { if (RoundParts > 2) {
assert(MVT::isVector(ValueVT) && "Unknown vector conversion!"); MVT::ValueType HalfVT = MVT::getIntegerType(RoundBits/2);
return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val); Lo = getCopyFromParts(DAG, Parts, RoundParts/2, PartVT, HalfVT);
} Hi = getCopyFromParts(DAG, Parts+RoundParts/2, RoundParts/2,
PartVT, HalfVT);
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);
} else { } 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 {
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. // Handle a multi-element vector.
MVT::ValueType IntermediateVT, RegisterVT; MVT::ValueType IntermediateVT, RegisterVT;
unsigned NumIntermediates; unsigned NumIntermediates;
unsigned NumRegs = unsigned NumRegs =
DAG.getTargetLoweringInfo() TLI.getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
.getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
RegisterVT); RegisterVT);
assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
@ -723,11 +716,54 @@ static SDOperand getCopyFromParts(SelectionDAG &DAG,
// Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
// operands. // operands.
return DAG.getNode(MVT::isVector(IntermediateVT) ? Val = DAG.getNode(MVT::isVector(IntermediateVT) ?
ISD::CONCAT_VECTORS : ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR,
ISD::BUILD_VECTOR,
ValueVT, &Ops[0], NumIntermediates); ValueVT, &Ops[0], NumIntermediates);
} }
}
// There is now one part, held in Val. Correct it to match ValueVT.
PartVT = Val.getValueType();
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(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 /// getCopyToParts - Create a series of nodes that contain the specified value
/// split into legal parts. If the parts contain more bits than Val, then, for /// split into legal parts. If the parts contain more bits than Val, then, for
@ -741,47 +777,113 @@ static void getCopyToParts(SelectionDAG &DAG,
TargetLowering &TLI = DAG.getTargetLoweringInfo(); TargetLowering &TLI = DAG.getTargetLoweringInfo();
MVT::ValueType PtrVT = TLI.getPointerTy(); MVT::ValueType PtrVT = TLI.getPointerTy();
MVT::ValueType ValueVT = Val.getValueType(); 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 (!NumParts)
// If the value was expanded, copy from the parts. return;
if (NumParts > 1) {
for (unsigned i = 0; i != NumParts; ++i) if (!MVT::isVector(ValueVT)) {
Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val, if (PartVT == ValueVT) {
DAG.getConstant(i, PtrVT)); assert(NumParts == 1 && "No-op copy with multiple parts!");
if (!DAG.getTargetLoweringInfo().isLittleEndian()) Parts[0] = Val;
std::reverse(Parts, Parts + NumParts);
return; return;
} }
// If there is a single part and the types differ, this must be if (NumParts * PartBits > MVT::getSizeInBits(ValueVT)) {
// a promotion. // If the parts cover more bits than the value has, promote the value.
if (PartVT != ValueVT) { if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT)) {
if (MVT::isVector(PartVT)) { assert(NumParts == 1 && "Do not know what to promote to!");
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)) {
Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val); Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
} else if (MVT::getSizeInBits(PartVT) == } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
MVT::getSizeInBits(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); 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 { } else {
assert(0 && "Unknown mismatch!"); 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; Parts[0] = Val;
return; return;
} }