Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ llvm/lib/Analysis/InstructionSimplify.cpp @@ -4841,18 +4841,23 @@ case Intrinsic::usub_with_overflow: case Intrinsic::ssub_with_overflow: // X - X -> { 0, false } - if (Op0 == Op1) + // X - undef -> { 0, false } for undef = X. + // undef - X -> { 0, false } for undef = X. + if (Op0 == Op1 || isa(Op0) || isa(Op1)) return Constant::getNullValue(ReturnType); - // X - undef -> undef - // undef - X -> undef - if (isa(Op0) || isa(Op1)) - return UndefValue::get(ReturnType); break; case Intrinsic::uadd_with_overflow: case Intrinsic::sadd_with_overflow: - // X + undef -> undef - if (isa(Op0) || isa(Op1)) - return UndefValue::get(ReturnType); + // X + undef -> { -1, false } for undef = ~X. + // undef + X -> { -1, false } for undef = ~X. + if (isa(Op0) || isa(Op1)) { + StructType *ST = cast(ReturnType); + Constant *Elems[] = { + Constant::getAllOnesValue(ST->getElementType(0)), + getFalse(ST->getElementType(1)), + }; + return ConstantStruct::get(ST, Elems); + } break; case Intrinsic::umul_with_overflow: case Intrinsic::smul_with_overflow: Index: llvm/test/Transforms/InstCombine/with_overflow.ll =================================================================== --- llvm/test/Transforms/InstCombine/with_overflow.ll +++ llvm/test/Transforms/InstCombine/with_overflow.ll @@ -60,7 +60,8 @@ define i8 @uaddtest4(i8 %A, i1* %overflowPtr) { ; CHECK-LABEL: @uaddtest4( -; CHECK-NEXT: ret i8 undef +; CHECK-NEXT: store i1 false, i1* [[OVERFLOWPTR:%.*]], align 1 +; CHECK-NEXT: ret i8 -1 ; %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 undef, i8 %A) %y = extractvalue { i8, i1 } %x, 0 Index: llvm/test/Transforms/InstSimplify/call.ll =================================================================== --- llvm/test/Transforms/InstSimplify/call.ll +++ llvm/test/Transforms/InstSimplify/call.ll @@ -29,7 +29,7 @@ define {i8, i1} @test_uadd3(i8 %v) { ; CHECK-LABEL: @test_uadd3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %v, i8 undef) ret {i8, i1} %result @@ -37,7 +37,7 @@ define {i8, i1} @test_uadd4(i8 %v) { ; CHECK-LABEL: @test_uadd4( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 undef, i8 %v) ret {i8, i1} %result @@ -63,7 +63,7 @@ define {i8, i1} @test_sadd3(i8 %v) { ; CHECK-LABEL: @test_sadd3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v, i8 undef) ret {i8, i1} %result @@ -71,7 +71,7 @@ define {i8, i1} @test_sadd4(i8 %v) { ; CHECK-LABEL: @test_sadd4( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 undef, i8 %v) ret {i8, i1} %result @@ -87,7 +87,7 @@ define {i8, i1} @test_usub2(i8 %V) { ; CHECK-LABEL: @test_usub2( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 undef) ret {i8, i1} %x @@ -95,7 +95,7 @@ define {i8, i1} @test_usub3(i8 %V) { ; CHECK-LABEL: @test_usub3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 undef, i8 %V) ret {i8, i1} %x @@ -111,7 +111,7 @@ define {i8, i1} @test_ssub2(i8 %V) { ; CHECK-LABEL: @test_ssub2( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 undef) ret {i8, i1} %x @@ -119,7 +119,7 @@ define {i8, i1} @test_ssub3(i8 %V) { ; CHECK-LABEL: @test_ssub3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 %V) ret {i8, i1} %x