When expanding unaligned loads and stores do not make

use of illegal integer types: instead, use a stack slot
and copying via integer registers.  The existing code
is still used if the bitconvert is to a legal integer
type.

This fires on the PPC testcases 2007-09-08-unaligned.ll
and vec_misaligned.ll.  It looks like equivalent code
is generated with these changes, just permuted, but
it's hard to tell.

With these changes, nothing in LegalizeDAG produces
illegal integer types anymore.  This is a prerequisite
for removing the LegalizeDAG type legalization code.

While there I noticed that the existing code doesn't
handle trunc store of f64 to f32: it turns this into
an i64 store, which represents a 4 byte stack smash.
I added a FIXME about this.  Hopefully someone more
motivated than I am will take care of it.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60964 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2008-12-12 21:47:02 +00:00
parent d350e02e19
commit 05e11fab87

View File

@ -630,21 +630,64 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
int SVOffset = ST->getSrcValueOffset();
if (ST->getMemoryVT().isFloatingPoint() ||
ST->getMemoryVT().isVector()) {
// Expand to a bitconvert of the value to the integer type of the
// same size, then a (misaligned) int store.
MVT intVT;
if (VT.is128BitVector() || VT == MVT::ppcf128 || VT == MVT::f128)
intVT = MVT::i128;
else if (VT.is64BitVector() || VT==MVT::f64)
intVT = MVT::i64;
else if (VT==MVT::f32)
intVT = MVT::i32;
else
assert(0 && "Unaligned store of unsupported type");
MVT intVT = MVT::getIntegerVT(VT.getSizeInBits());
if (TLI.isTypeLegal(intVT)) {
// Expand to a bitconvert of the value to the integer type of the
// same size, then a (misaligned) int store.
// FIXME: Does not handle truncating floating point stores!
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, intVT, Val);
return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(),
SVOffset, ST->isVolatile(), Alignment);
} else {
// Do a (aligned) store to a stack slot, then copy from the stack slot
// to the final destination using (unaligned) integer loads and stores.
MVT StoredVT = ST->getMemoryVT();
MVT RegVT =
TLI.getRegisterType(MVT::getIntegerVT(StoredVT.getSizeInBits()));
unsigned StoredBytes = StoredVT.getSizeInBits() / 8;
unsigned RegBytes = RegVT.getSizeInBits() / 8;
unsigned NumRegs = (StoredBytes + RegBytes - 1) / RegBytes;
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, intVT, Val);
return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(),
SVOffset, ST->isVolatile(), Alignment);
// Make sure the stack slot is wide enough that we can do NumRegs full
// width loads from it.
SDValue StackPtr = DAG.CreateStackTemporary(StoredVT,
MVT::getIntegerVT(NumRegs * RegBytes * 8));
// Perform the original store only redirected to the stack slot.
SDValue Store = DAG.getTruncStore(Chain, Val, StackPtr, NULL, 0,StoredVT);
SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy());
SmallVector<SDValue, 8> Stores;
unsigned Offset = 0;
// Do all but one copies using the full register width.
for (unsigned i = 1; i < NumRegs; i++) {
// Load one integer register's worth from the stack slot.
SDValue Load = DAG.getLoad(RegVT, Store, StackPtr, NULL, 0);
// Store it to the final location. Remember the store.
Stores.push_back(DAG.getStore(Load.getValue(1), Load, Ptr,
ST->getSrcValue(), SVOffset + Offset,
ST->isVolatile(),
MinAlign(ST->getAlignment(), Offset)));
// Increment the pointers.
Offset += RegBytes;
StackPtr = DAG.getNode(ISD::ADD, StackPtr.getValueType(), StackPtr,
Increment);
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, Increment);
}
// Load one integer register's worth from the stack slot.
SDValue Load = DAG.getLoad(RegVT, Store, StackPtr, NULL, 0);
// The last store may be partial. Do a truncating store.
unsigned BytesLeft = StoredBytes - Offset;
Stores.push_back(DAG.getTruncStore(Load.getValue(1), Load, Ptr,
ST->getSrcValue(), SVOffset + Offset,
MVT::getIntegerVT(BytesLeft * 8),
ST->isVolatile(),
MinAlign(ST->getAlignment(), Offset)));
// The order of the stores doesn't matter - say it with a TokenFactor.
return DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0],
Stores.size());
}
}
assert(ST->getMemoryVT().isInteger() &&
!ST->getMemoryVT().isVector() &&
@ -685,28 +728,74 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
MVT VT = LD->getValueType(0);
MVT LoadedVT = LD->getMemoryVT();
if (VT.isFloatingPoint() || VT.isVector()) {
// Expand to a (misaligned) integer load of the same size,
// then bitconvert to floating point or vector.
MVT intVT;
if (LoadedVT.is128BitVector() ||
LoadedVT == MVT::ppcf128 || LoadedVT == MVT::f128)
intVT = MVT::i128;
else if (LoadedVT.is64BitVector() || LoadedVT == MVT::f64)
intVT = MVT::i64;
else if (LoadedVT == MVT::f32)
intVT = MVT::i32;
else
assert(0 && "Unaligned load of unsupported type");
SDValue newLoad = DAG.getLoad(intVT, Chain, Ptr, LD->getSrcValue(),
SVOffset, LD->isVolatile(),
MVT intVT = MVT::getIntegerVT(LoadedVT.getSizeInBits());
if (TLI.isTypeLegal(intVT)) {
// Expand to a (misaligned) integer load of the same size,
// then bitconvert to floating point or vector.
SDValue newLoad = DAG.getLoad(intVT, Chain, Ptr, LD->getSrcValue(),
SVOffset, LD->isVolatile(),
LD->getAlignment());
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, LoadedVT, newLoad);
if (VT.isFloatingPoint() && LoadedVT != VT)
Result = DAG.getNode(ISD::FP_EXTEND, VT, Result);
SDValue Result = DAG.getNode(ISD::BIT_CONVERT, LoadedVT, newLoad);
if (VT.isFloatingPoint() && LoadedVT != VT)
Result = DAG.getNode(ISD::FP_EXTEND, VT, Result);
SDValue Ops[] = { Result, Chain };
return DAG.getMergeValues(Ops, 2);
SDValue Ops[] = { Result, Chain };
return DAG.getMergeValues(Ops, 2);
} else {
// Copy the value to a (aligned) stack slot using (unaligned) integer
// loads and stores, then do a (aligned) load from the stack slot.
MVT RegVT = TLI.getRegisterType(intVT);
unsigned LoadedBytes = LoadedVT.getSizeInBits() / 8;
unsigned RegBytes = RegVT.getSizeInBits() / 8;
unsigned NumRegs = (LoadedBytes + RegBytes - 1) / RegBytes;
// Make sure the stack slot wide enough that we can do NumRegs full width
// stores to it.
SDValue StackBase = DAG.CreateStackTemporary(LoadedVT,
MVT::getIntegerVT(NumRegs * RegBytes * 8));
SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy());
SmallVector<SDValue, 8> Stores;
SDValue StackPtr = StackBase;
unsigned Offset = 0;
// Do all but one copies using the full register width.
for (unsigned i = 1; i < NumRegs; i++) {
// Load one integer register's worth from the original location.
SDValue Load = DAG.getLoad(RegVT, Chain, Ptr, LD->getSrcValue(),
SVOffset + Offset, LD->isVolatile(),
MinAlign(LD->getAlignment(), Offset));
// Follow the load with a store to the stack slot. Remember the store.
Stores.push_back(DAG.getStore(Load.getValue(1), Load, StackPtr,
NULL, 0));
// Increment the pointers.
Offset += RegBytes;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, Increment);
StackPtr = DAG.getNode(ISD::ADD, StackPtr.getValueType(), StackPtr,
Increment);
}
// The last copy may be partial. Do an extending load.
unsigned BytesLeft = LoadedBytes - Offset;
SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, RegVT, Chain, Ptr,
LD->getSrcValue(), SVOffset + Offset,
MVT::getIntegerVT(BytesLeft * 8),
LD->isVolatile(),
MinAlign(LD->getAlignment(), Offset));
// Follow the load with a store to the stack slot. Remember the store.
Stores.push_back(DAG.getStore(Load.getValue(1), Load, StackPtr, NULL, 0));
// The order of the stores doesn't matter - say it with a TokenFactor.
SDValue TF = DAG.getNode(ISD::TokenFactor, MVT::Other, &Stores[0],
Stores.size());
// Finally, perform the original load only redirected to the stack slot.
Load = DAG.getExtLoad(LD->getExtensionType(), VT, TF, StackBase,
NULL, 0, LoadedVT);
// Callers expect a MERGE_VALUES node.
SDValue Ops[] = { Load, TF };
return DAG.getMergeValues(Ops, 2);
}
}
assert(LoadedVT.isInteger() && !LoadedVT.isVector() &&
"Unaligned load of unsupported type.");