[DAG] disable nsw/nuw for add/sub/mul when simplifying based on demanded bits (PR30841)
authorSanjay Patel <spatel@rotateright.com>
Mon, 31 Oct 2016 23:28:45 +0000 (23:28 +0000)
committerSanjay Patel <spatel@rotateright.com>
Mon, 31 Oct 2016 23:28:45 +0000 (23:28 +0000)
This bug was exposed by using nsw/nuw for more aggressive folds in:
https://reviews.llvm.org/rL284844

The changes mimic the IR demanded bits logic in InstCombiner::SimplifyDemandedUseBits(),
but we can't just flip flag bits in the DAG; we have to create a new node that has the
bits cleared.

This should fix:
https://llvm.org/bugs/show_bug.cgi?id=30841

llvm-svn: 285656

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
llvm/test/CodeGen/X86/add-sub-nsw-nuw.ll [new file with mode: 0644]

index 1228298..487af80 100644 (file)
@@ -1216,14 +1216,25 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
     APInt LoMask = APInt::getLowBitsSet(BitWidth,
                                         BitWidth - NewMask.countLeadingZeros());
     if (SimplifyDemandedBits(Op.getOperand(0), LoMask, KnownZero2,
-                             KnownOne2, TLO, Depth+1))
-      return true;
-    if (SimplifyDemandedBits(Op.getOperand(1), LoMask, KnownZero2,
-                             KnownOne2, TLO, Depth+1))
-      return true;
-    // See if the operation should be performed at a smaller bit width.
-    if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl))
+                             KnownOne2, TLO, Depth+1) ||
+        SimplifyDemandedBits(Op.getOperand(1), LoMask, KnownZero2,
+                             KnownOne2, TLO, Depth+1) ||
+        // See if the operation should be performed at a smaller bit width.
+        TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) {
+      const SDNodeFlags *Flags = Op.getNode()->getFlags();
+      if (Flags->hasNoSignedWrap() || Flags->hasNoUnsignedWrap()) {
+        // Disable the nsw and nuw flags. We can no longer guarantee that we
+        // won't wrap after simplification.
+        SDNodeFlags NewFlags = *Flags;
+        NewFlags.setNoSignedWrap(false);
+        NewFlags.setNoUnsignedWrap(false);
+        SDValue NewOp = TLO.DAG.getNode(Op.getOpcode(), dl, Op.getValueType(),
+                                        Op.getOperand(0), Op.getOperand(1),
+                                        &NewFlags);
+        return TLO.CombineTo(Op, NewOp);
+      }
       return true;
+    }
     LLVM_FALLTHROUGH;
   }
   default:
diff --git a/llvm/test/CodeGen/X86/add-sub-nsw-nuw.ll b/llvm/test/CodeGen/X86/add-sub-nsw-nuw.ll
new file mode 100644 (file)
index 0000000..f5bffb2
--- /dev/null
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: llc -mtriple=i386-apple-darwin < %s | FileCheck %s
+
+; PR30841: https://llvm.org/bugs/show_bug.cgi?id=30841
+; Demanded bits analysis must disable nsw/nuw when it makes a
+; simplification to add/sub such as in this case.
+
+define i8 @PR30841(i64 %argc) {
+; CHECK-LABEL: PR30841:
+; CHECK:       ## BB#0: ## %entry
+; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT:    negl %eax
+; CHECK-NEXT:    ## kill: %AL<def> %AL<kill> %EAX<kill>
+; CHECK-NEXT:    retl
+;
+entry:
+  %or = or i64 %argc, -4294967296
+  br label %end
+
+end:
+  %neg = sub nuw nsw i64 -4294967296, %argc
+  %trunc = trunc i64 %neg to i8
+  ret i8 %trunc
+}
+