aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2012-02-28 17:58:00 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2012-02-28 17:58:00 +0000
commit3bf15ced2b91661ac314911c1f28332da0e1c37c (patch)
tree73b480a3b1612372c3c122f9b17834e1141f18e2 /lib/CodeGen
parent20bd5296cec8d8d597ab9db2aca7346a88e580c8 (diff)
downloadexternal_llvm-3bf15ced2b91661ac314911c1f28332da0e1c37c.zip
external_llvm-3bf15ced2b91661ac314911c1f28332da0e1c37c.tar.gz
external_llvm-3bf15ced2b91661ac314911c1f28332da0e1c37c.tar.bz2
LegalizeIntegerTypes: Reenable the large shift with small amount optimization.
To avoid problems with zero shifts when getting the bits that move between words we use a trick: first shift the by amount-1, then do another shift by one. When amount is 0 (and size 32) we first shift by 31, then by one, instead of by 32. Also fix a latent bug that emitted the low and high words in the wrong order when shifting right. Fixes PR12113. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151637 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp32
1 files changed, 21 insertions, 11 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index d18766a..38467c5 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -1397,15 +1397,15 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) {
}
}
-#if 0
- // FIXME: This code is broken for shifts with a zero amount!
// If we know that all of the high bits of the shift amount are zero, then we
// can do this as a couple of simple shifts.
if ((KnownZero & HighBitMask) == HighBitMask) {
- // Compute 32-amt.
- SDValue Amt2 = DAG.getNode(ISD::SUB, ShTy,
- DAG.getConstant(NVTBits, ShTy),
- Amt);
+ // Calculate 31-x. 31 is used instead of 32 to avoid creating an undefined
+ // shift if x is zero. We can use XOR here because x is known to be smaller
+ // than 31.
+ SDValue Amt2 = DAG.getNode(ISD::XOR, dl, ShTy, Amt,
+ DAG.getConstant(NVTBits-1, ShTy));
+
unsigned Op1, Op2;
switch (N->getOpcode()) {
default: llvm_unreachable("Unknown shift");
@@ -1414,13 +1414,23 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) {
case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break;
}
- Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt);
- Hi = DAG.getNode(ISD::OR, NVT,
- DAG.getNode(Op1, NVT, InH, Amt),
- DAG.getNode(Op2, NVT, InL, Amt2));
+ // When shifting right the arithmetic for Lo and Hi is swapped.
+ if (N->getOpcode() != ISD::SHL)
+ std::swap(InL, InH);
+
+ // Use a little trick to get the bits that move from Lo to Hi. First
+ // calculate the shift with amount-1.
+ SDValue Sh1 = DAG.getNode(Op2, dl, NVT, InL, Amt2);
+ // Then shift one bit further to get the right result.
+ SDValue Sh2 = DAG.getNode(Op2, dl, NVT, Sh1, DAG.getConstant(1, ShTy));
+
+ Lo = DAG.getNode(N->getOpcode(), dl, NVT, InL, Amt);
+ Hi = DAG.getNode(ISD::OR, dl, NVT, DAG.getNode(Op1, dl, NVT, InH, Amt),Sh2);
+
+ if (N->getOpcode() != ISD::SHL)
+ std::swap(Hi, Lo);
return true;
}
-#endif
return false;
}