[DAGCombiner] Use APInt directly in (shl (ext (shl x, c1)), c2) combine
authorSimon Pilgrim <llvm-dev@redking.me.uk>
Tue, 13 Sep 2016 17:15:28 +0000 (17:15 +0000)
committerSimon Pilgrim <llvm-dev@redking.me.uk>
Tue, 13 Sep 2016 17:15:28 +0000 (17:15 +0000)
Fix failure to detect out of range shift constants leading to assert in ConstantSDNode::getZExtValue()

Followup to D23007

llvm-svn: 281354

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/X86/shift-i128.ll

index d1727a1..c449c7d 100644 (file)
@@ -4518,18 +4518,22 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
       N0.getOperand(0).getOpcode() == ISD::SHL) {
     SDValue N0Op0 = N0.getOperand(0);
     if (ConstantSDNode *N0Op0C1 = isConstOrConstSplat(N0Op0.getOperand(1))) {
-      uint64_t c1 = N0Op0C1->getZExtValue();
-      uint64_t c2 = N1C->getZExtValue();
+      APInt c1 = N0Op0C1->getAPIntValue();
+      APInt c2 = N1C->getAPIntValue();
+      zeroExtendToMatch(c1, c2, 1 /* Overflow Bit */);
+
       EVT InnerShiftVT = N0Op0.getValueType();
       uint64_t InnerShiftSize = InnerShiftVT.getScalarSizeInBits();
-      if (c2 >= OpSizeInBits - InnerShiftSize) {
+      if (c2.uge(OpSizeInBits - InnerShiftSize)) {
         SDLoc DL(N0);
-        if (c1 + c2 >= OpSizeInBits)
+        APInt Sum = c1 + c2;
+        if (Sum.uge(OpSizeInBits))
           return DAG.getConstant(0, DL, VT);
-        return DAG.getNode(ISD::SHL, DL, VT,
-                           DAG.getNode(N0.getOpcode(), DL, VT,
-                                       N0Op0->getOperand(0)),
-                           DAG.getConstant(c1 + c2, DL, N1.getValueType()));
+
+        return DAG.getNode(
+            ISD::SHL, DL, VT,
+            DAG.getNode(N0.getOpcode(), DL, VT, N0Op0->getOperand(0)),
+            DAG.getConstant(Sum.getZExtValue(), DL, N1.getValueType()));
       }
     }
   }
@@ -5264,11 +5268,11 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
     if (N0->getOpcode() == ISD::XOR) {
       if (auto *C = dyn_cast<ConstantSDNode>(N0->getOperand(1))) {
         SDValue Cond0 = N0->getOperand(0);
-        if (C->isOne()) 
-          return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), 
+        if (C->isOne())
+          return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(),
                              Cond0, N2, N1);
         else
-          return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(), 
+          return DAG.getNode(ISD::SELECT, SDLoc(N), N1.getValueType(),
                              Cond0, N1, N2);
       }
     }
index aef923f..1de99b1 100644 (file)
@@ -116,3 +116,21 @@ entry:
        store <2 x i128> %1, <2 x i128>* %r, align 16
        ret void
 }
+
+;
+; Combines
+;
+
+define <2 x i256> @shl_sext_shl_outofrange(<2 x i128> %a0) {
+  %1 = shl <2 x i128> %a0, <i128 -1, i128 -1>
+  %2 = sext <2 x i128> %1 to <2 x i256>
+  %3 = shl <2 x i256> %2, <i256 128, i256 128>
+  ret <2 x i256> %3
+}
+
+define <2 x i256> @shl_zext_shl_outofrange(<2 x i128> %a0) {
+  %1 = shl <2 x i128> %a0, <i128 -1, i128 -1>
+  %2 = zext <2 x i128> %1 to <2 x i256>
+  %3 = shl <2 x i256> %2, <i256 128, i256 128>
+  ret <2 x i256> %3
+}