[llvm-branch-commits] [llvm] f094d65 - [InstSimplify] Fix addo/subo with undef (PR43188)
Nikita Popov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Jan 3 10:01:52 PST 2021
Author: Nikita Popov
Date: 2021-01-03T18:51:49+01:00
New Revision: f094d65beaa492e845b03561eddd75b5be653a01
URL: https://github.com/llvm/llvm-project/commit/f094d65beaa492e845b03561eddd75b5be653a01
DIFF: https://github.com/llvm/llvm-project/commit/f094d65beaa492e845b03561eddd75b5be653a01.diff
LOG: [InstSimplify] Fix addo/subo with undef (PR43188)
We can't fold the first result to undef, because not all values
may be reachable under the constraint that no overflow occurred.
Use the same folds we do for saturated math instead.
Proofs:
uaddo: https://alive2.llvm.org/ce/z/zf55N_
saddo: https://alive2.llvm.org/ce/z/a_xPgS
usubo: https://alive2.llvm.org/ce/z/DmRqwt
ssubo: https://alive2.llvm.org/ce/z/8ag7U-
Added:
Modified:
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/test/Transforms/InstCombine/with_overflow.ll
llvm/test/Transforms/InstSimplify/call.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 16b5fd5436f9..4706969eafc0 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5444,19 +5444,19 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1,
case Intrinsic::usub_with_overflow:
case Intrinsic::ssub_with_overflow:
// X - X -> { 0, false }
- if (Op0 == Op1)
+ // X - undef -> { 0, false }
+ // undef - X -> { 0, false }
+ if (Op0 == Op1 || Q.isUndefValue(Op0) || Q.isUndefValue(Op1))
return Constant::getNullValue(ReturnType);
- LLVM_FALLTHROUGH;
+ break;
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 (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) {
return ConstantStruct::get(
cast<StructType>(ReturnType),
- {UndefValue::get(ReturnType->getStructElementType(0)),
+ {Constant::getAllOnesValue(ReturnType->getStructElementType(0)),
Constant::getNullValue(ReturnType->getStructElementType(1))});
}
break;
diff --git a/llvm/test/Transforms/InstCombine/with_overflow.ll b/llvm/test/Transforms/InstCombine/with_overflow.ll
index 84b5042e6186..4553c9f56965 100644
--- a/llvm/test/Transforms/InstCombine/with_overflow.ll
+++ b/llvm/test/Transforms/InstCombine/with_overflow.ll
@@ -61,7 +61,7 @@ define i8 @uaddtest3(i8 %A, i8 %B, i1* %overflowPtr) {
define i8 @uaddtest4(i8 %A, i1* %overflowPtr) {
; CHECK-LABEL: @uaddtest4(
; CHECK-NEXT: store i1 false, i1* [[OVERFLOWPTR:%.*]], align 1
-; CHECK-NEXT: ret i8 undef
+; CHECK-NEXT: ret i8 -1
;
%x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 undef, i8 %A)
%y = extractvalue { i8, i1 } %x, 0
diff --git a/llvm/test/Transforms/InstSimplify/call.ll b/llvm/test/Transforms/InstSimplify/call.ll
index 841582ab8974..bb7410ada7d5 100644
--- a/llvm/test/Transforms/InstSimplify/call.ll
+++ b/llvm/test/Transforms/InstSimplify/call.ll
@@ -29,7 +29,7 @@ define i8 @test_uadd2() {
define {i8, i1} @test_uadd3(i8 %v) {
; CHECK-LABEL: @test_uadd3(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; 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_uadd3(i8 %v) {
define {i8, i1} @test_uadd3_poison(i8 %v) {
; CHECK-LABEL: @test_uadd3_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false }
;
%result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %v, i8 poison)
ret {i8, i1} %result
@@ -45,7 +45,7 @@ define {i8, i1} @test_uadd3_poison(i8 %v) {
define {i8, i1} @test_uadd4(i8 %v) {
; CHECK-LABEL: @test_uadd4(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; 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
@@ -53,7 +53,7 @@ define {i8, i1} @test_uadd4(i8 %v) {
define {i8, i1} @test_uadd4_poison(i8 %v) {
; CHECK-LABEL: @test_uadd4_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false }
;
%result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 poison, i8 %v)
ret {i8, i1} %result
@@ -79,7 +79,7 @@ define i8 @test_sadd2() {
define {i8, i1} @test_sadd3(i8 %v) {
; CHECK-LABEL: @test_sadd3(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; 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
@@ -87,7 +87,7 @@ define {i8, i1} @test_sadd3(i8 %v) {
define {i8, i1} @test_sadd3_poison(i8 %v) {
; CHECK-LABEL: @test_sadd3_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false }
;
%result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 %v, i8 poison)
ret {i8, i1} %result
@@ -95,7 +95,7 @@ define {i8, i1} @test_sadd3_poison(i8 %v) {
define {i8, i1} @test_sadd4(i8 %v) {
; CHECK-LABEL: @test_sadd4(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; 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
@@ -103,7 +103,7 @@ define {i8, i1} @test_sadd4(i8 %v) {
define {i8, i1} @test_sadd4_poison(i8 %v) {
; CHECK-LABEL: @test_sadd4_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } { i8 -1, i1 false }
;
%result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 poison, i8 %v)
ret {i8, i1} %result
@@ -119,7 +119,7 @@ define {i8, i1} @test_usub1(i8 %V) {
define {i8, i1} @test_usub2(i8 %V) {
; CHECK-LABEL: @test_usub2(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 undef)
ret {i8, i1} %x
@@ -127,7 +127,7 @@ define {i8, i1} @test_usub2(i8 %V) {
define {i8, i1} @test_usub2_poison(i8 %V) {
; CHECK-LABEL: @test_usub2_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %V, i8 poison)
ret {i8, i1} %x
@@ -135,7 +135,7 @@ define {i8, i1} @test_usub2_poison(i8 %V) {
define {i8, i1} @test_usub3(i8 %V) {
; CHECK-LABEL: @test_usub3(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 undef, i8 %V)
ret {i8, i1} %x
@@ -143,7 +143,7 @@ define {i8, i1} @test_usub3(i8 %V) {
define {i8, i1} @test_usub3_poison(i8 %V) {
; CHECK-LABEL: @test_usub3_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.usub.with.overflow.i8(i8 poison, i8 %V)
ret {i8, i1} %x
@@ -159,7 +159,7 @@ define {i8, i1} @test_ssub1(i8 %V) {
define {i8, i1} @test_ssub2(i8 %V) {
; CHECK-LABEL: @test_ssub2(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 undef)
ret {i8, i1} %x
@@ -167,7 +167,7 @@ define {i8, i1} @test_ssub2(i8 %V) {
define {i8, i1} @test_ssub2_poison(i8 %V) {
; CHECK-LABEL: @test_ssub2_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %V, i8 poison)
ret {i8, i1} %x
@@ -175,7 +175,7 @@ define {i8, i1} @test_ssub2_poison(i8 %V) {
define {i8, i1} @test_ssub3(i8 %V) {
; CHECK-LABEL: @test_ssub3(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 %V)
ret {i8, i1} %x
@@ -183,7 +183,7 @@ define {i8, i1} @test_ssub3(i8 %V) {
define {i8, i1} @test_ssub3_poison(i8 %V) {
; CHECK-LABEL: @test_ssub3_poison(
-; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false }
+; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 poison, i8 %V)
ret {i8, i1} %x
More information about the llvm-branch-commits
mailing list