From: David Majnemer Date: Fri, 22 Aug 2014 07:56:32 +0000 (+0000) Subject: InstCombine: Don't unconditionally preserve 'nsw' when shrinking constants X-Git-Tag: android-x86-7.1-r4~58225 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c86bdc73e8b3f69708fafc1ce957216062c995cd;p=android-x86%2Fexternal-llvm.git InstCombine: Don't unconditionally preserve 'nsw' when shrinking constants 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 --- diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 1b42d3d504a..c26766a95ac 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -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(I)) + if (OBO->hasNoSignedWrap() && OpC->getValue().isNegative()) + cast(OBO)->setHasNoSignedWrap(false); + return true; } diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 86e9f3f5335..81b0d7eff52 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -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 +}