summaryrefslogtreecommitdiff
path: root/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-18 10:14:55 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-18 10:14:55 +0000
commit9dffd71d0af3d78ee1f21865dd064fb43bc623be (patch)
treeb93aa63b62d21fa6a20218d9ba9e75f83e6cccd2 /lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
parent30a132f7676ec5465a2245cb94e7bd9214ea8eb7 (diff)
downloadllvm-9dffd71d0af3d78ee1f21865dd064fb43bc623be.tar.gz
llvm-9dffd71d0af3d78ee1f21865dd064fb43bc623be.tar.bz2
llvm-9dffd71d0af3d78ee1f21865dd064fb43bc623be.tar.xz
[SystemZ] Generalize RxSBG SRA case
The original code only folded SRA into ROTATE ... SELECTED BITS if there was no outer shift. This patch splits out that check and generalises it slightly. The extra cases aren't really that interesting, but this is paving the way for RNSBG support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186571 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZISelDAGToDAG.cpp63
1 files changed, 36 insertions, 27 deletions
diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
index 67e9d217ee..0f9a37ed0c 100644
--- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
+++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -647,9 +647,29 @@ static bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) {
return false;
}
+// RxSBG.Input is a shift of Count bits in the direction given by IsLeft.
+// Return true if the result depends on the signs or zeros that are
+// shifted in.
+static bool shiftedInBitsMatter(RxSBGOperands &RxSBG, uint64_t Count,
+ bool IsLeft) {
+ // Work out which bits of the shift result are zeros or sign copies.
+ uint64_t ShiftedIn = allOnes(Count);
+ if (!IsLeft)
+ ShiftedIn <<= RxSBG.BitSize - Count;
+
+ // Rotate that mask in the same way as RxSBG.Input is rotated.
+ if (RxSBG.Rotate != 0)
+ ShiftedIn = ((ShiftedIn << RxSBG.Rotate) |
+ (ShiftedIn >> (64 - RxSBG.Rotate)));
+
+ // Fail if any of the zero or sign bits are used.
+ return (ShiftedIn & RxSBG.Mask) != 0;
+}
+
bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) {
SDValue N = RxSBG.Input;
- switch (N.getOpcode()) {
+ unsigned Opcode = N.getOpcode();
+ switch (Opcode) {
case ISD::AND: {
ConstantSDNode *MaskNode =
dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
@@ -704,41 +724,30 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) {
return true;
}
- case ISD::SRL: {
- // Treat (srl X, count), mask) as (and (rotl X, size-count), ~0>>count),
- // which is similar to SLL above.
- ConstantSDNode *CountNode =
- dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
- if (!CountNode)
- return false;
-
- uint64_t Count = CountNode->getZExtValue();
- if (Count < 1 ||
- Count >= RxSBG.BitSize ||
- !refineRxSBGMask(RxSBG, allOnes(RxSBG.BitSize - Count)))
- return false;
-
- RxSBG.Rotate = (RxSBG.Rotate - Count) & 63;
- RxSBG.Input = N.getOperand(0);
- return true;
- }
-
+ case ISD::SRL:
case ISD::SRA: {
- // Treat (sra X, count) as (rotl X, size-count) as long as the top
- // count bits from Ops.Input are ignored.
ConstantSDNode *CountNode =
dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
if (!CountNode)
return false;
uint64_t Count = CountNode->getZExtValue();
- if (RxSBG.Rotate != 0 ||
- Count < 1 ||
- Count >= RxSBG.BitSize ||
- RxSBG.Start < 64 - (RxSBG.BitSize - Count))
+ if (Count < 1 || Count >= RxSBG.BitSize)
return false;
- RxSBG.Rotate = -Count & 63;
+ if (Opcode == ISD::SRA) {
+ // Treat (sra X, count) as (rotl X, size-count) as long as the top
+ // Count bits from RxSBG.Input are ignored.
+ if (shiftedInBitsMatter(RxSBG, Count, false))
+ return false;
+ } else {
+ // Treat (srl X, count), mask) as (and (rotl X, size-count), ~0>>count),
+ // which is similar to SLL above.
+ if (!refineRxSBGMask(RxSBG, allOnes(RxSBG.BitSize - Count)))
+ return false;
+ }
+
+ RxSBG.Rotate = (RxSBG.Rotate - Count) & 63;
RxSBG.Input = N.getOperand(0);
return true;
}