InstCombine: Don't unconditionally preserve 'nsw' when shrinking constants
authorDavid Majnemer <david.majnemer@gmail.com>
Fri, 22 Aug 2014 07:56:32 +0000 (07:56 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Fri, 22 Aug 2014 07:56:32 +0000 (07:56 +0000)
Consider:
  %add = add nsw i32 %a, -16777216
  %and = and i32 %add, 255

Regardless of whether or not we demand the sign bit of %add, we cannot
replace -16777216 with 2130706432 without also removing 'nsw' from the
instruction.

This fixes PR20377.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216261 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
test/Transforms/InstCombine/cast.ll

index 1b42d3d504a3d57dbceb54729c0c59b9e6eac159..c26766a95ac4fdd8672cd4242b126e7c34573ee5 100644 (file)
@@ -43,6 +43,14 @@ static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo,
   // This instruction is producing bits that are not demanded. Shrink the RHS.
   Demanded &= OpC->getValue();
   I->setOperand(OpNo, ConstantInt::get(OpC->getType(), Demanded));
+
+  // If 'nsw' is set and the constant is negative, removing *any* bits from the
+  // constant could make overflow occur.  Remove 'nsw' from the instruction in
+  // this case.
+  if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I))
+    if (OBO->hasNoSignedWrap() && OpC->getValue().isNegative())
+      cast<BinaryOperator>(OBO)->setHasNoSignedWrap(false);
+
   return true;
 }
 
index 86e9f3f5335952aada60ab2770bad8bc2952a5f1..81b0d7eff52f1e8937e306d4a80059bf0dcb19be 100644 (file)
@@ -1022,7 +1022,19 @@ define i64 @test83(i16 %a, i64 %k) {
   ret i64 %sh_prom1
 
 ; CHECK-LABEL: @test83(
-; CHECK: %sub = add nsw i64 %k, 4294967295
+; CHECK: %sub = add i64 %k, 4294967295
 ; CHECK: %sh_prom = trunc i64 %sub to i32
 ; CHECK: %shl = shl i32 %conv, %sh_prom
 }
+
+define i8 @test84(i32 %a) {
+  %add = add nsw i32 %a, -16777216
+  %shr = lshr exact i32 %add, 23
+  %trunc = trunc i32 %shr to i8
+  ret i8 %trunc
+
+; CHECK-LABEL: @test84(
+; CHECK: [[ADD:%.*]] = add i32 %a, 2130706432
+; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23
+; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8
+}