From 7949a2a802f0791eaf7c6ecbdd6ed5daa2a278cf Mon Sep 17 00:00:00 2001 From: Zhongyunde Date: Wed, 22 Mar 2023 19:52:41 +0800 Subject: [PATCH] [InstCombine] enhance icmp with sub folds The new IR with And removes a use of the input variable, which is better for analysis. Fix https://github.com/llvm/llvm-project/issues/60818 Reviewed By: nikic, spatel Differential Revision: https://reviews.llvm.org/D145846 --- .../Transforms/InstCombine/InstCombineCompares.cpp | 38 +++++++++++++++------- llvm/test/Transforms/InstCombine/icmp-sub.ll | 16 ++++----- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 421b182..1666c06 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4065,20 +4065,36 @@ Value *InstCombinerImpl::foldMultiplicationOverflowCheck(ICmpInst &I) { return Res; } -static Instruction *foldICmpXNegX(ICmpInst &I) { +static Instruction *foldICmpXNegX(ICmpInst &I, + InstCombiner::BuilderTy &Builder) { CmpInst::Predicate Pred; Value *X; - if (!match(&I, m_c_ICmp(Pred, m_NSWNeg(m_Value(X)), m_Deferred(X)))) - return nullptr; + if (match(&I, m_c_ICmp(Pred, m_NSWNeg(m_Value(X)), m_Deferred(X)))) { - if (ICmpInst::isSigned(Pred)) - Pred = ICmpInst::getSwappedPredicate(Pred); - else if (ICmpInst::isUnsigned(Pred)) - Pred = ICmpInst::getSignedPredicate(Pred); - // else for equality-comparisons just keep the predicate. + if (ICmpInst::isSigned(Pred)) + Pred = ICmpInst::getSwappedPredicate(Pred); + else if (ICmpInst::isUnsigned(Pred)) + Pred = ICmpInst::getSignedPredicate(Pred); + // else for equality-comparisons just keep the predicate. + + return ICmpInst::Create(Instruction::ICmp, Pred, X, + Constant::getNullValue(X->getType()), I.getName()); + } - return ICmpInst::Create(Instruction::ICmp, Pred, X, - Constant::getNullValue(X->getType()), I.getName()); + // A value is not equal to its negation unless that value is 0 or + // MinSignedValue, ie: a != -a --> (a & MaxSignedVal) != 0 + if (match(&I, m_c_ICmp(Pred, m_OneUse(m_Neg(m_Value(X))), m_Deferred(X))) && + ICmpInst::isEquality(Pred)) { + Type *Ty = X->getType(); + uint32_t BitWidth = Ty->getScalarSizeInBits(); + Constant *MaxSignedVal = + ConstantInt::get(Ty, APInt::getSignedMaxValue(BitWidth)); + Value *And = Builder.CreateAnd(X, MaxSignedVal); + Constant *Zero = Constant::getNullValue(Ty); + return CmpInst::Create(Instruction::ICmp, Pred, And, Zero); + } + + return nullptr; } /// Try to fold icmp (binop), X or icmp X, (binop). @@ -4096,7 +4112,7 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, if (!BO0 && !BO1) return nullptr; - if (Instruction *NewICmp = foldICmpXNegX(I)) + if (Instruction *NewICmp = foldICmpXNegX(I, Builder)) return NewICmp; const CmpInst::Predicate Pred = I.getPredicate(); diff --git a/llvm/test/Transforms/InstCombine/icmp-sub.ll b/llvm/test/Transforms/InstCombine/icmp-sub.ll index 68f1585..2dad575 100644 --- a/llvm/test/Transforms/InstCombine/icmp-sub.ll +++ b/llvm/test/Transforms/InstCombine/icmp-sub.ll @@ -566,8 +566,8 @@ bb_exit: define i1 @PR60818_ne(i32 %a) { ; CHECK-LABEL: @PR60818_ne( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[SUB]], [[A]] +; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP0]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; entry: @@ -579,8 +579,8 @@ entry: define i1 @PR60818_eq(i32 %a) { ; CHECK-LABEL: @PR60818_eq( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SUB]], [[A]] +; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; entry: @@ -593,8 +593,8 @@ define i1 @PR60818_eq_commuted(i32 %x) { ; CHECK-LABEL: @PR60818_eq_commuted( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = mul i32 [[X:%.*]], 43 -; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], [[SUB]] +; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[A]], 2147483647 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 ; CHECK-NEXT: ret i1 [[CMP]] ; entry: @@ -607,8 +607,8 @@ entry: define <2 x i1> @PR60818_ne_vector(<2 x i32> %a) { ; CHECK-LABEL: @PR60818_ne_vector( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[A:%.*]] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[SUB]], [[A]] +; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i32> [[A:%.*]], +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i32> [[TMP0]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; entry: -- 2.7.4