[llvm] r186571 - [SystemZ] Generalize RxSBG SRA case

Richard Sandiford rsandifo at linux.vnet.ibm.com
Thu Jul 18 03:14:55 PDT 2013


Author: rsandifo
Date: Thu Jul 18 05:14:55 2013
New Revision: 186571

URL: http://llvm.org/viewvc/llvm-project?rev=186571&view=rev
Log:
[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.

Modified:
    llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
    llvm/trunk/test/CodeGen/SystemZ/risbg-01.ll

Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp?rev=186571&r1=186570&r2=186571&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp Thu Jul 18 05:14:55 2013
@@ -647,9 +647,29 @@ static bool refineRxSBGMask(RxSBGOperand
   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(Rx
     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;
   }

Modified: llvm/trunk/test/CodeGen/SystemZ/risbg-01.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/risbg-01.ll?rev=186571&r1=186570&r2=186571&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/risbg-01.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/risbg-01.ll Thu Jul 18 05:14:55 2013
@@ -416,3 +416,41 @@ define i64 @f37(i64 %foo) {
   %shl = lshr i64 %and, 1
   ret i64 %shl
 }
+
+; Test a combination involving a large ASHR and a shift left.  We can't
+; use RISBG there.
+define i64 @f38(i64 %foo) {
+; CHECK-LABEL: f38:
+; CHECK: srag {{%r[0-5]}}
+; CHECK: sllg {{%r[0-5]}}
+; CHECK: br %r14
+  %ashr = ashr i64 %foo, 32
+  %shl = shl i64 %ashr, 5
+  ret i64 %shl
+}
+
+; Try a similar thing in which no shifted sign bits are kept.
+define i64 @f39(i64 %foo, i64 *%dest) {
+; CHECK-LABEL: f39:
+; CHECK: srag [[REG:%r[01345]]], %r2, 35
+; CHECK: risbg %r2, %r2, 33, 189, 31
+; CHECK: br %r14
+  %ashr = ashr i64 %foo, 35
+  store i64 %ashr, i64 *%dest
+  %shl = shl i64 %ashr, 2
+  %and = and i64 %shl, 2147483647
+  ret i64 %and
+}
+
+; ...and again with the next highest shift value, where one sign bit is kept.
+define i64 @f40(i64 %foo, i64 *%dest) {
+; CHECK-LABEL: f40:
+; CHECK: srag [[REG:%r[01345]]], %r2, 36
+; CHECK: risbg %r2, [[REG]], 33, 189, 2
+; CHECK: br %r14
+  %ashr = ashr i64 %foo, 36
+  store i64 %ashr, i64 *%dest
+  %shl = shl i64 %ashr, 2
+  %and = and i64 %shl, 2147483647
+  ret i64 %and
+}





More information about the llvm-commits mailing list