[PATCH] D23570: Fix SystemZ compilation abort caused by negative AND mask

Elliot Colp via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 17 08:55:34 PDT 2016


colpell updated this revision to Diff 68370.
colpell added a comment.

Update combineSHIFTROT comment.


https://reviews.llvm.org/D23570

Files:
  lib/Target/SystemZ/SystemZISelLowering.cpp
  test/CodeGen/SystemZ/shift-11.ll

Index: test/CodeGen/SystemZ/shift-11.ll
===================================================================
--- test/CodeGen/SystemZ/shift-11.ll
+++ test/CodeGen/SystemZ/shift-11.ll
@@ -61,3 +61,25 @@
   %shift = shl i64 %a, %and
   ret i64 %shift
 }
+
+; Test shift with negative 32-bit value.
+define i32 @f8(i32 %a, i32 %sh, i32 %test) {
+; CHECK-LABEL: f8:
+; CHECK: nill %r3, 65529
+; CHECK: sll %r2, 0(%r3)
+  %and = and i32 %sh, -7
+  %shift = shl i32 %a, %and
+
+  ret i32 %shift
+}
+
+; Test shift with negative 64-bit value.
+define i64 @f9(i64 %a, i64 %sh, i64 %test) {
+; CHECK-LABEL: f9:
+; CHECK: nill %r3, 65529
+; CHECK: sllg %r2, %r2, 0(%r3)
+  %and = and i64 %sh, -7
+  %shift = shl i64 %a, %and
+
+  ret i64 %shift
+}
Index: lib/Target/SystemZ/SystemZISelLowering.cpp
===================================================================
--- lib/Target/SystemZ/SystemZISelLowering.cpp
+++ lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -5070,14 +5070,19 @@
   // Shift/rotate instructions only use the last 6 bits of the second operand
   // register. If the second operand is the result of an AND with an immediate
   // value that has its last 6 bits set, we can safely remove the AND operation.
+  //
+  // If the AND operation doesn't have the last 6 bits set, we can't remove it
+  // entirely, but we can still truncate it to a 16-bit value. This prevents
+  // us from ending up with a NILL with a signed operand, which will cause the
+  // instruction printer to abort.
   SDValue N1 = N->getOperand(1);
   if (N1.getOpcode() == ISD::AND) {
-    auto *AndMask = dyn_cast<ConstantSDNode>(N1.getOperand(1));
+    SDValue AndMaskOp = N1->getOperand(1);
+    auto *AndMask = dyn_cast<ConstantSDNode>(AndMaskOp);
+    auto AmtVal = AndMask->getZExtValue();
 
     // The AND mask is constant
     if (AndMask) {
-      auto AmtVal = AndMask->getZExtValue();
-
       // Bottom 6 bits are set
       if ((AmtVal & 0x3f) == 0x3f) {
         SDValue AndOp = N1->getOperand(0);
@@ -5099,6 +5104,25 @@
 
           return Replace;
         }
+
+      // We can't remove the AND, but we can use NILL here (normally we would
+      // use NILF). Only keep the last 16 bits of the mask.
+      } else if (AmtVal >> 16 != 0) {
+        SDValue AndOp = N1->getOperand(0);
+
+        auto NewMask = DAG.getConstant(AndMask->getZExtValue() & 0x0000ffff,
+                                       SDLoc(AndMaskOp),
+                                       AndMaskOp.getValueType());
+
+        auto NewAnd = DAG.getNode(N1.getOpcode(), SDLoc(N1), N1.getValueType(),
+                                  AndOp, NewMask);
+
+        SDValue Replace = DAG.getNode(N->getOpcode(), SDLoc(N),
+                                      N->getValueType(0), N->getOperand(0),
+                                      NewAnd);
+        DCI.AddToWorklist(Replace.getNode());
+
+        return Replace;
       }
     }
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23570.68370.patch
Type: text/x-patch
Size: 2908 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160817/ddd5bf95/attachment.bin>


More information about the llvm-commits mailing list