From 05e11fab87102a230551327bfc8434ffad7a88d4 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Fri, 12 Dec 2008 21:47:02 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 157 ++++++++++++++++++----- 1 file changed, 123 insertions(+), 34 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 0a10e4f6d81..6671e0f2fb3 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -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; + + // 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 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); - SDValue Result = DAG.getNode(ISD::BIT_CONVERT, intVT, Val); - return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(), - SVOffset, ST->isVolatile(), Alignment); + // 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 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."); -- 2.34.1