diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index bb1cbfade34..274758ccb4b 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1657,6 +1657,14 @@ static Instruction *ProcessUGT_ADDCST_ADD(ICmpInst &I, Value *A, Value *B, CI1->getValue() != APInt::getLowBitsSet(CI1->getBitWidth(), NewWidth)) return 0; + // This is only really a signed overflow check if the inputs have been + // sign-extended; check for that condition. For example, if CI2 is 2^31 and + // the operands of the add are 64 bits wide, we need at least 33 sign bits. + unsigned NeededSignBits = CI1->getBitWidth() - NewWidth + 1; + if (IC.ComputeNumSignBits(A) < NeededSignBits || + IC.ComputeNumSignBits(B) < NeededSignBits) + return 0; + // In order to replace the original add with a narrower // llvm.sadd.with.overflow, the only uses allowed are the add-with-constant // and truncates that discard the high bits of the add. Verify that this is diff --git a/test/Transforms/InstCombine/overflow.ll b/test/Transforms/InstCombine/overflow.ll index 9123283988d..81ceef8c41c 100644 --- a/test/Transforms/InstCombine/overflow.ll +++ b/test/Transforms/InstCombine/overflow.ll @@ -130,4 +130,26 @@ entry: ret i64 %Q } +; CHECK: @test8 +; PR11438 +; This is @test1, but the operands are not sign-extended. Make sure +; we don't transform this case. +define i32 @test8(i64 %a, i64 %b) nounwind ssp { +entry: +; CHECK-NOT: llvm.sadd +; CHECK: add i64 %a, %b +; CHECK-NOT: llvm.sadd +; CHECK: ret + %add = add i64 %a, %b + %add.off = add i64 %add, 2147483648 + %0 = icmp ugt i64 %add.off, 4294967295 + br i1 %0, label %if.then, label %if.end +if.then: + tail call void @throwAnExceptionOrWhatever() nounwind + br label %if.end + +if.end: + %conv9 = trunc i64 %add to i32 + ret i32 %conv9 +}