diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index c26766a95ac..f0c96bdf768 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -44,12 +44,18 @@ static bool ShrinkDemandedConstant(Instruction *I, unsigned OpNo, 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); + // If either 'nsw' or 'nuw' is set and the constant is negative, + // removing *any* bits from the constant could make overflow occur. + // Remove 'nsw' and 'nuw' from the instruction in this case. + if (auto *OBO = dyn_cast(I)) { + assert(OBO->getOpcode() == Instruction::Add); + if (OBO->hasNoSignedWrap() || OBO->hasNoUnsignedWrap()) { + if (OpC->getValue().isNegative()) { + cast(OBO)->setHasNoSignedWrap(false); + cast(OBO)->setHasNoUnsignedWrap(false); + } + } + } return true; } diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 81b0d7eff52..47f7e73f998 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -1038,3 +1038,15 @@ define i8 @test84(i32 %a) { ; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23 ; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 } + +define i8 @test85(i32 %a) { + %add = add nuw i32 %a, -16777216 + %shr = lshr exact i32 %add, 23 + %trunc = trunc i32 %shr to i8 + ret i8 %trunc + +; CHECK-LABEL: @test85( +; CHECK: [[ADD:%.*]] = add i32 %a, 2130706432 +; CHECK: [[SHR:%.*]] = lshr exact i32 [[ADD]], 23 +; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8 +}