aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2007-10-22 19:00:05 +0000
committerDuncan Sands <baldrick@free.fr>2007-10-22 19:00:05 +0000
commitfec3ad3e5f98ffdafee873c4afed81648ff2049f (patch)
treeefdb735628744a506f5d27778d69f4395fa4dc34
parent246b2564d3bbbafe06ebf6a67745cd24141b5cb4 (diff)
downloadexternal_llvm-fec3ad3e5f98ffdafee873c4afed81648ff2049f.zip
external_llvm-fec3ad3e5f98ffdafee873c4afed81648ff2049f.tar.gz
external_llvm-fec3ad3e5f98ffdafee873c4afed81648ff2049f.tar.bz2
Support for expanding extending loads of integers with
funky bit-widths. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43225 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp87
1 files changed, 71 insertions, 16 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
index f056f6f..e5f8edd 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
+++ b/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) {