[InstSimplify] Simplify uadd/sadd/umul/smul with overflow intrinsics when the Zero or Undef is on the LHS.

Summary: This code was migrated from InstCombine a few years ago. InstCombine had nearby code that would move Constants to the RHS for these, but InstSimplify doesn't have such code on this path.

Reviewers: spatel, majnemer, davide

Reviewed By: spatel

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D33473

llvm-svn: 303774
This commit is contained in:
Craig Topper 2017-05-24 17:05:28 +00:00
parent 8205a1a9b6
commit 77e07cc010
2 changed files with 53 additions and 3 deletions

View File

@ -4440,19 +4440,21 @@ static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd,
case Intrinsic::uadd_with_overflow: case Intrinsic::uadd_with_overflow:
case Intrinsic::sadd_with_overflow: { case Intrinsic::sadd_with_overflow: {
// X + undef -> undef // X + undef -> undef
if (isa<UndefValue>(RHS)) if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS))
return UndefValue::get(ReturnType); return UndefValue::get(ReturnType);
return nullptr; return nullptr;
} }
case Intrinsic::umul_with_overflow: case Intrinsic::umul_with_overflow:
case Intrinsic::smul_with_overflow: { case Intrinsic::smul_with_overflow: {
// 0 * X -> { 0, false }
// X * 0 -> { 0, false } // X * 0 -> { 0, false }
if (match(RHS, m_Zero())) if (match(LHS, m_Zero()) || match(RHS, m_Zero()))
return Constant::getNullValue(ReturnType); return Constant::getNullValue(ReturnType);
// undef * X -> { 0, false }
// X * undef -> { 0, false } // X * undef -> { 0, false }
if (match(RHS, m_Undef())) if (match(LHS, m_Undef()) || match(RHS, m_Undef()))
return Constant::getNullValue(ReturnType); return Constant::getNullValue(ReturnType);
return nullptr; return nullptr;

View File

@ -35,6 +35,14 @@ define {i8, i1} @test_uadd3(i8 %v) {
ret {i8, i1} %result ret {i8, i1} %result
} }
define {i8, i1} @test_uadd4(i8 %v) {
; CHECK-LABEL: @test_uadd4(
; CHECK-NEXT: ret { i8, i1 } undef
;
%result = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 undef, i8 %v)
ret {i8, i1} %result
}
define i1 @test_sadd1() { define i1 @test_sadd1() {
; CHECK-LABEL: @test_sadd1( ; CHECK-LABEL: @test_sadd1(
; CHECK-NEXT: ret i1 true ; CHECK-NEXT: ret i1 true
@ -61,6 +69,14 @@ define {i8, i1} @test_sadd3(i8 %v) {
ret {i8, i1} %result ret {i8, i1} %result
} }
define {i8, i1} @test_sadd4(i8 %v) {
; CHECK-LABEL: @test_sadd4(
; CHECK-NEXT: ret { i8, i1 } undef
;
%result = call {i8, i1} @llvm.sadd.with.overflow.i8(i8 undef, i8 %v)
ret {i8, i1} %result
}
define {i8, i1} @test_usub1(i8 %V) { define {i8, i1} @test_usub1(i8 %V) {
; CHECK-LABEL: @test_usub1( ; CHECK-LABEL: @test_usub1(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; CHECK-NEXT: ret { i8, i1 } zeroinitializer
@ -125,6 +141,22 @@ define {i8, i1} @test_umul2(i8 %V) {
ret {i8, i1} %x ret {i8, i1} %x
} }
define {i8, i1} @test_umul3(i8 %V) {
; CHECK-LABEL: @test_umul3(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 0, i8 %V)
ret {i8, i1} %x
}
define {i8, i1} @test_umul4(i8 %V) {
; CHECK-LABEL: @test_umul4(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.umul.with.overflow.i8(i8 undef, i8 %V)
ret {i8, i1} %x
}
define {i8, i1} @test_smul1(i8 %V) { define {i8, i1} @test_smul1(i8 %V) {
; CHECK-LABEL: @test_smul1( ; CHECK-LABEL: @test_smul1(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer ; CHECK-NEXT: ret { i8, i1 } zeroinitializer
@ -141,6 +173,22 @@ define {i8, i1} @test_smul2(i8 %V) {
ret {i8, i1} %x ret {i8, i1} %x
} }
define {i8, i1} @test_smul3(i8 %V) {
; CHECK-LABEL: @test_smul3(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 0, i8 %V)
ret {i8, i1} %x
}
define {i8, i1} @test_smul4(i8 %V) {
; CHECK-LABEL: @test_smul4(
; CHECK-NEXT: ret { i8, i1 } zeroinitializer
;
%x = call {i8, i1} @llvm.smul.with.overflow.i8(i8 undef, i8 %V)
ret {i8, i1} %x
}
declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef) declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef)
define i256 @test_cttz() { define i256 @test_cttz() {