From d09f140cd1ebdfcabc333c45fe7e7fe59752bdf9 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 16 Jun 2019 20:39:45 +0000 Subject: [PATCH] [InstSimplify] Fix addo/subo undef folds (PR42209) Fix folds of addo and subo with an undef operand to be: `@llvm.{u,s}{add,sub}.with.overflow` all fold to `{ undef, false }`, as per LLVM undef rules. Same for commuted variants. Based on the original version of the patch by @nikic. Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=42209 | PR42209 ]] Differential Revision: https://reviews.llvm.org/D63065 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363522 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 19 +++++++++++-------- test/Transforms/InstCombine/with_overflow.ll | 1 + test/Transforms/InstSimplify/call.ll | 16 ++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index d0b9549d3ae..ba76c5b0479 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -4843,16 +4843,19 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, // X - X -> { 0, false } if (Op0 == Op1) return Constant::getNullValue(ReturnType); - // X - undef -> undef - // undef - X -> undef - if (isa(Op0) || isa(Op1)) - return UndefValue::get(ReturnType); - break; + LLVM_FALLTHROUGH; case Intrinsic::uadd_with_overflow: case Intrinsic::sadd_with_overflow: - // X + undef -> undef - if (isa(Op0) || isa(Op1)) - return UndefValue::get(ReturnType); + // X - undef -> { undef, false } + // undef - X -> { undef, false } + // X + undef -> { undef, false } + // undef + x -> { undef, false } + if (isa(Op0) || isa(Op1)) { + return ConstantStruct::get( + cast(ReturnType), + {UndefValue::get(ReturnType->getStructElementType(0)), + Constant::getNullValue(ReturnType->getStructElementType(1))}); + } break; case Intrinsic::umul_with_overflow: case Intrinsic::smul_with_overflow: diff --git a/test/Transforms/InstCombine/with_overflow.ll b/test/Transforms/InstCombine/with_overflow.ll index b15e37ce6e0..04e8097ca7d 100644 --- a/test/Transforms/InstCombine/with_overflow.ll +++ b/test/Transforms/InstCombine/with_overflow.ll @@ -60,6 +60,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 ; %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 undef, i8 %A) diff --git a/test/Transforms/InstSimplify/call.ll b/test/Transforms/InstSimplify/call.ll index 0771e4453e3..27497e5e862 100644 --- a/test/Transforms/InstSimplify/call.ll +++ b/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 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, 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_uadd4(i8 %v) { ; CHECK-LABEL: @test_uadd4( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, 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 @test_sadd2() { define {i8, i1} @test_sadd3(i8 %v) { ; CHECK-LABEL: @test_sadd3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, 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_sadd3(i8 %v) { define {i8, i1} @test_sadd4(i8 %v) { ; CHECK-LABEL: @test_sadd4( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, 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_usub1(i8 %V) { define {i8, i1} @test_usub2(i8 %V) { ; CHECK-LABEL: @test_usub2( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } ; %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_usub2(i8 %V) { define {i8, i1} @test_usub3(i8 %V) { ; CHECK-LABEL: @test_usub3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } ; %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_ssub1(i8 %V) { define {i8, i1} @test_ssub2(i8 %V) { ; CHECK-LABEL: @test_ssub2( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } ; %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_ssub2(i8 %V) { define {i8, i1} @test_ssub3(i8 %V) { ; CHECK-LABEL: @test_ssub3( -; CHECK-NEXT: ret { i8, i1 } undef +; CHECK-NEXT: ret { i8, i1 } { i8 undef, i1 false } ; %x = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 undef, i8 %V) ret {i8, i1} %x -- 2.11.0