diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2519,16 +2519,19 @@ case Intrinsic::usub_with_overflow: case Intrinsic::ssub_with_overflow: + // X - undef -> { 0, false } + // undef - X -> { 0, false } + if (!C0 || !C1) + return Constant::getNullValue(Ty); + LLVM_FALLTHROUGH; case Intrinsic::uadd_with_overflow: case Intrinsic::sadd_with_overflow: - // X - undef -> { undef, false } - // undef - X -> { undef, false } - // X + undef -> { undef, false } - // undef + x -> { undef, false } + // X + undef -> { -1, false } + // undef + x -> { -1, false } if (!C0 || !C1) { return ConstantStruct::get( cast(Ty), - {UndefValue::get(Ty->getStructElementType(0)), + {Constant::getAllOnesValue(Ty->getStructElementType(0)), Constant::getNullValue(Ty->getStructElementType(1))}); } LLVM_FALLTHROUGH; diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/overflow-ops.ll b/llvm/test/Transforms/InstSimplify/ConstProp/overflow-ops.ll --- a/llvm/test/Transforms/InstSimplify/ConstProp/overflow-ops.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/overflow-ops.ll @@ -31,7 +31,7 @@ define {i8, i1} @uadd_undef() nounwind { ; CHECK-LABEL: @uadd_undef( -; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %t = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 142, i8 undef) ret {i8, i1} %t @@ -59,7 +59,7 @@ define {i8, i1} @usub_undef() nounwind { ; CHECK-LABEL: @usub_undef( -; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %t = call {i8, i1} @llvm.usub.with.overflow.i8(i8 4, i8 undef) ret {i8, i1} %t @@ -147,7 +147,7 @@ define {i8, i1} @sadd_undef() nounwind { ; CHECK-LABEL: @sadd_undef( -; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } +; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false } ; %t = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 undef, i8 -10) ret {i8, i1} %t @@ -215,7 +215,7 @@ define {i8, i1} @ssub_undef() nounwind { ; CHECK-LABEL: @ssub_undef( -; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } +; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; %t = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 -10) ret {i8, i1} %t