diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp | 87 | 
1 files changed, 71 insertions, 16 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp index f056f6f3f72..e5f8edd57d8 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp @@ -935,17 +935,19 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,    int SVOffset = N->getSrcValueOffset();    unsigned Alignment = N->getAlignment();    bool isVolatile = N->isVolatile(); -   + +  assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!"); +    if (ExtType == ISD::NON_EXTLOAD) {      Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,                       isVolatile, Alignment);      // Increment the pointer to the other half. -    unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8; +    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;      Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,                        getIntPtrConstant(IncrementSize));      Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,                       isVolatile, std::max(Alignment, IncrementSize)); -     +      // Build a factor node to remember that this load is independent of the      // other one.      Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), @@ -954,19 +956,15 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,      // Handle endianness of the load.      if (!TLI.isLittleEndian())        std::swap(Lo, Hi); -  } else { +  } else if (MVT::getSizeInBits(N->getLoadedVT()) <= MVT::getSizeInBits(NVT)) {      MVT::ValueType EVT = N->getLoadedVT(); -     -    if (EVT == NVT) -      Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), -                       SVOffset, isVolatile, Alignment); -    else -      Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), -                          SVOffset, EVT, isVolatile, -                          Alignment); + +    Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT, +                        isVolatile, Alignment); +      // Remember the chain.      Ch = Lo.getValue(1); -     +      if (ExtType == ISD::SEXTLOAD) {        // The high part is obtained by SRA'ing all but one of the bits of the        // lo part. @@ -981,13 +979,70 @@ void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,        // The high part is undefined.        Hi = DAG.getNode(ISD::UNDEF, NVT);      } +  } else if (TLI.isLittleEndian()) { +    // Little-endian - low bits are at low addresses. +    Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, +                     isVolatile, Alignment); + +    unsigned ExcessBits = +      MVT::getSizeInBits(N->getLoadedVT()) - 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.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), +                        SVOffset+IncrementSize, NEVT, +                        isVolatile, std::max(Alignment, IncrementSize)); + +    // Build a factor node to remember that this load is independent of the +    // other one. +    Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), +                     Hi.getValue(1)); +  } else { +    // Big-endian - high bits are at low addresses.  Favor aligned loads at +    // the cost of some bit-fiddling. +    MVT::ValueType EVT = N->getLoadedVT(); +    unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8; +    unsigned IncrementSize = MVT::getSizeInBits(NVT)/8; +    unsigned ExcessBits = (EBytes - IncrementSize)*8; + +    // Load both the high bits and maybe some of the low bits. +    Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, +                        MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits), +                        isVolatile, Alignment); + +    // Increment the pointer to the other half. +    Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, +                      getIntPtrConstant(IncrementSize)); +    // Load the rest of the low bits. +    Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(), +                        SVOffset+IncrementSize, MVT::getIntegerType(ExcessBits), +                        isVolatile, std::max(Alignment, IncrementSize)); + +    // Build a factor node to remember that this load is independent of the +    // other one. +    Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), +                     Hi.getValue(1)); + +    if (ExcessBits < MVT::getSizeInBits(NVT)) { +      // Transfer low bits from the bottom of Hi to the top of Lo. +      Lo = DAG.getNode(ISD::OR, NVT, Lo, +                       DAG.getNode(ISD::SHL, NVT, Hi, +                                   DAG.getConstant(ExcessBits, +                                                   TLI.getShiftAmountTy()))); +      // Move high bits to the right position in Hi. +      Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi, +                       DAG.getConstant(MVT::getSizeInBits(NVT) - ExcessBits, +                                       TLI.getShiftAmountTy())); +    }    } -   +    // Legalized the chain result - switch anything that used the old chain to    // use the new one.    ReplaceLegalValueWith(SDOperand(N, 1), Ch); -}   - +}  void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,                                              SDOperand &Lo, SDOperand &Hi) { | 

