Add support for expanding trunc stores. Consider

storing an i170 on a 32 bit machine.  This is first
promoted to a trunc-i170 store of an i256.  On a
little-endian machine this expands to a store of
an i128 and a trunc-i42 store of an i128.  The
trunc-i42 store is further expanded to a trunc-i42
store of an i64, then to a store of an i32 and a
trunc-i10 store of an i32.  At this point the operand
type is legal (i32) and expansion stops (legalization
of the trunc-i10 needs to be handled in LegalizeDAG.cpp).
On big-endian machines the high bits are stored first,
and some bit-fiddling is needed in order to generate
aligned stores.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43499 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2007-10-30 12:50:39 +00:00
parent ba3b1d10fd
commit 01405f9284

View File

@ -1936,75 +1936,139 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
assert(OpNo == 1 && "Can only expand the stored value so far");
assert(!N->isTruncatingStore() && "Can't expand truncstore!");
unsigned IncrementSize = 0;
SDOperand Lo, Hi;
// 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 (MVT::isVector(N->getValue().getValueType())) {
assert(0 && "Vectors not supported yet");
#if 0
SDNode *InVal = ST->getValue().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 normal store of the vector type.
Tmp3 = LegalizeOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
Result = LegalizeOp(Result);
break;
} else if (NumElems == 1) {
// Turn this into a normal store of the scalar type.
Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
// The scalarized value type may not be legal, e.g. it might require
// promotion or expansion. Relegalize the scalar store.
return LegalizeOp(Result);
} else {
SplitVectorOp(Node->getOperand(1), Lo, Hi);
IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
}
#endif
} else {
GetExpandedOp(N->getValue(), Lo, Hi);
IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
if (!TLI.isLittleEndian())
std::swap(Lo, Hi);
}
SDOperand Chain = N->getChain();
SDOperand Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
MVT::ValueType VT = N->getOperand(1).getValueType();
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
SDOperand Ch = N->getChain();
SDOperand Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
bool isVolatile = N->isVolatile();
Lo = DAG.getStore(Chain, Lo, Ptr, N->getSrcValue(),
SVOffset, isVolatile, Alignment);
assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
#if 0
if (Hi.Val == NULL) {
// Must be int <-> float one-to-one expansion.
return Lo;
bool isVolatile = N->isVolatile();
SDOperand Lo, Hi;
assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
if (!N->isTruncatingStore()) {
unsigned IncrementSize = 0;
// 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 (MVT::isVector(N->getValue().getValueType())) {
assert(0 && "Vectors not supported yet");
#if 0
SDNode *InVal = ST->getValue().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 normal store of the vector type.
Tmp3 = LegalizeOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
Result = LegalizeOp(Result);
break;
} else if (NumElems == 1) {
// Turn this into a normal store of the scalar type.
Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
// The scalarized value type may not be legal, e.g. it might require
// promotion or expansion. Relegalize the scalar store.
return LegalizeOp(Result);
} else {
SplitVectorOp(Node->getOperand(1), Lo, Hi);
IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
}
#endif
} else {
GetExpandedOp(N->getValue(), Lo, Hi);
IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
if (!TLI.isLittleEndian())
std::swap(Lo, Hi);
}
Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
SVOffset, isVolatile, Alignment);
assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
#if 0
if (Hi.Val == NULL) {
// Must be int <-> float one-to-one expansion.
return Lo;
}
#endif
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVolatile, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
} else if (MVT::getSizeInBits(N->getStoredVT()) <= MVT::getSizeInBits(NVT)) {
GetExpandedOp(N->getValue(), Lo, Hi);
return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
N->getStoredVT(), isVolatile, Alignment);
} else if (TLI.isLittleEndian()) {
// Little-endian - low bits are at low addresses.
GetExpandedOp(N->getValue(), Lo, Hi);
Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
isVolatile, Alignment);
unsigned ExcessBits =
MVT::getSizeInBits(N->getStoredVT()) - MVT::getSizeInBits(NVT);
MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
// Increment the pointer to the other half.
unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
SVOffset+IncrementSize, NEVT,
isVolatile, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
} else {
// Big-endian - high bits are at low addresses. Favor aligned stores at
// the cost of some bit-fiddling.
GetExpandedOp(N->getValue(), Lo, Hi);
MVT::ValueType EVT = N->getStoredVT();
unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
unsigned ExcessBits = (EBytes - IncrementSize)*8;
MVT::ValueType HiVT =
MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits);
if (ExcessBits < MVT::getSizeInBits(NVT)) {
// Transfer high bits from the top of Lo to the bottom of Hi.
Hi = DAG.getNode(ISD::SHL, NVT, Hi,
DAG.getConstant(MVT::getSizeInBits(NVT) - ExcessBits,
TLI.getShiftAmountTy()));
Hi = DAG.getNode(ISD::OR, NVT, Hi,
DAG.getNode(ISD::SRL, NVT, Lo,
DAG.getConstant(ExcessBits,
TLI.getShiftAmountTy())));
}
// Store both the high bits and maybe some of the low bits.
Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
SVOffset, HiVT, isVolatile, Alignment);
// Increment the pointer to the other half.
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
// Store the lowest ExcessBits bits in the second half.
Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(),
SVOffset+IncrementSize,
MVT::getIntegerType(ExcessBits),
isVolatile, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
}
#endif
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
Hi = DAG.getStore(Chain, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVolatile, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
}