From 9c5a4a4527bc6c06b0f889501aa48aa23ccb90a5 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 14 Sep 2019 13:47:27 +0000 Subject: [PATCH] [InstSimplify] simplifyUnsignedRangeCheck(): handle few tautological cases (PR43251) Summary: This is split off from D67356, since these cases produce a constant, no real need to keep them in instcombine. Alive proofs: https://rise4fun.com/Alive/u7Fk https://rise4fun.com/Alive/4lV https://bugs.llvm.org/show_bug.cgi?id=43251 Reviewers: spatel, nikic, xbolva00 Reviewed By: spatel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67498 llvm-svn: 371921 --- llvm/lib/Analysis/InstructionSimplify.cpp | 53 +++++++++++++++------- .../result-of-usub-is-non-zero-and-no-overflow.ll | 18 +++----- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index defa3c3..cfb37f4 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1382,23 +1382,44 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp, ICmpInst::Predicate UnsignedPred; - // Y = (A - B); Y >= A && Y != 0 --> Y >= A iff B != 0 - // Y = (A - B); Y < A || Y == 0 --> Y < A iff B != 0 Value *A, *B; - if (match(Y, m_Sub(m_Value(A), m_Value(B))) && - match(UnsignedICmp, - m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) { - if (UnsignedICmp->getOperand(0) != Y) - UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred); - - if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd && - EqPred == ICmpInst::ICMP_NE && - isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) - return UnsignedICmp; - if (UnsignedPred == ICmpInst::ICMP_ULT && !IsAnd && - EqPred == ICmpInst::ICMP_EQ && - isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) - return UnsignedICmp; + // Y = (A - B); + if (match(Y, m_Sub(m_Value(A), m_Value(B)))) { + if (match(UnsignedICmp, + m_c_ICmp(UnsignedPred, m_Specific(A), m_Specific(B))) && + ICmpInst::isUnsigned(UnsignedPred)) { + if (UnsignedICmp->getOperand(0) != A) + UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred); + + // A >=/<= B || (A - B) != 0 <--> true + if ((UnsignedPred == ICmpInst::ICMP_UGE || + UnsignedPred == ICmpInst::ICMP_ULE) && + EqPred == ICmpInst::ICMP_NE && !IsAnd) + return ConstantInt::getTrue(UnsignedICmp->getType()); + // A B && (A - B) == 0 <--> false + if ((UnsignedPred == ICmpInst::ICMP_ULT || + UnsignedPred == ICmpInst::ICMP_UGT) && + EqPred == ICmpInst::ICMP_EQ && IsAnd) + return ConstantInt::getFalse(UnsignedICmp->getType()); + } + + // Given Y = (A - B) + // Y >= A && Y != 0 --> Y >= A iff B != 0 + // Y < A || Y == 0 --> Y < A iff B != 0 + if (match(UnsignedICmp, + m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) { + if (UnsignedICmp->getOperand(0) != Y) + UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred); + + if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd && + EqPred == ICmpInst::ICMP_NE && + isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + return UnsignedICmp; + if (UnsignedPred == ICmpInst::ICMP_ULT && !IsAnd && + EqPred == ICmpInst::ICMP_EQ && + isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT)) + return UnsignedICmp; + } } if (match(UnsignedICmp, m_ICmp(UnsignedPred, m_Value(X), m_Specific(Y))) && diff --git a/llvm/test/Transforms/InstSimplify/result-of-usub-is-non-zero-and-no-overflow.ll b/llvm/test/Transforms/InstSimplify/result-of-usub-is-non-zero-and-no-overflow.ll index fcc4831..476528f 100644 --- a/llvm/test/Transforms/InstSimplify/result-of-usub-is-non-zero-and-no-overflow.ll +++ b/llvm/test/Transforms/InstSimplify/result-of-usub-is-non-zero-and-no-overflow.ll @@ -22,8 +22,7 @@ define i1 @t1(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) -; CHECK-NEXT: [[R:%.*]] = or i1 [[NOT_NULL]], [[NO_UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) @@ -62,8 +61,7 @@ define i1 @t1_commutativity(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) -; CHECK-NEXT: [[R:%.*]] = or i1 [[NOT_NULL]], [[NO_UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) @@ -86,8 +84,7 @@ define i1 @t2(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]]) ; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NULL]]) -; CHECK-NEXT: [[R:%.*]] = and i1 [[NULL]], [[UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) @@ -126,8 +123,7 @@ define i1 @t2_commutativity(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[UNDERFLOW]]) ; CHECK-NEXT: [[NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NULL]]) -; CHECK-NEXT: [[R:%.*]] = and i1 [[NULL]], [[UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) @@ -148,8 +144,7 @@ define i1 @t3(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) -; CHECK-NEXT: [[R:%.*]] = or i1 [[NOT_NULL]], [[NO_UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) @@ -170,8 +165,7 @@ define i1 @t4(i8 %base, i8 %offset) { ; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) ; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 ; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) -; CHECK-NEXT: [[R:%.*]] = and i1 [[NOT_NULL]], [[NO_UNDERFLOW]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %adjusted = sub i8 %base, %offset call void @use8(i8 %adjusted) -- 2.7.4