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

Elliot Colp via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 16 09:05:41 PDT 2016


colpell created this revision.
colpell added a reviewer: uweigand.
colpell added a subscriber: llvm-commits.

Normally, when an AND with a constant is lowered to NILL, the constant value is truncated to 16 bits. However, since r274066, ANDs whose results are used in a shift are caught by a different pattern that does not truncate. The instruction printer expects a 16-bit unsigned immediate operand for NILL, so this results in an abort.

This patch adds code to manually truncate the constant in this situation.

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
@@ -5072,12 +5072,12 @@
   // value that has its last 6 bits set, we can safely remove the AND operation.
   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 +5099,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.68196.patch
Type: text/x-patch
Size: 2469 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160816/ee414dfd/attachment.bin>


More information about the llvm-commits mailing list