diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1382,23 +1382,42 @@ 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); + // Y = (A - B); + if (match(Y, m_Sub(m_Value(A), m_Value(B)))) { + // A >= B || (A - B) != 0 <--> true + // A < B && (A - B) == 0 <--> false + 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); - 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 (UnsignedPred == ICmpInst::ICMP_UGE && EqPred == ICmpInst::ICMP_NE && + !IsAnd) + return ConstantInt::getTrue(UnsignedICmp->getType()); + if (UnsignedPred == ICmpInst::ICMP_ULT && 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 --- 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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)