[PATCH] D145846: [InstCombine] enhance icmp with sub folds

Allen zhong via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 11 06:30:48 PST 2023


Allen created this revision.
Allen added reviewers: spatel, david-arm, lebedev.ri.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
Allen requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

According the comment on D144324 <https://reviews.llvm.org/D144324>, The new IR with and removes a use of the input variable,
so it's better for analysis.


https://reviews.llvm.org/D145846

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
  llvm/test/Transforms/InstCombine/icmp-sub.ll


Index: llvm/test/Transforms/InstCombine/icmp-sub.ll
===================================================================
--- llvm/test/Transforms/InstCombine/icmp-sub.ll
+++ llvm/test/Transforms/InstCombine/icmp-sub.ll
@@ -561,3 +561,30 @@
 bb_exit:
   ret void
 }
+
+; https://alive2.llvm.org/ce/z/D2Aph4
+define i1 @PR60818_ne(i32 %a) {
+; CHECK-LABEL: @PR60818_ne(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %sub = sub i32 0, %a
+  %cmp = icmp ne i32 %sub, %a
+  ret i1 %cmp
+}
+
+define i1 @PR60818_eq(i32 %a) {
+; CHECK-LABEL: @PR60818_eq(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = and i32 [[A:%.*]], 2147483647
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %sub = sub i32 0, %a
+  %cmp = icmp eq i32 %sub, %a
+  ret i1 %cmp
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4074,20 +4074,36 @@
   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_Neg(m_Value(X)), m_Deferred(X))) &&
+      (Pred == ICmpInst::ICMP_NE || Pred == ICmpInst::ICMP_EQ)) {
+    Type *Ty = X->getType();
+    uint32_t BitWidth = cast<IntegerType>(Ty)->getBitWidth();
+    Constant *MaxSignedVal =
+        ConstantInt::get(Ty, APInt::getSignedMaxValue(BitWidth));
+    Value *And = Builder.CreateAnd(X, MaxSignedVal);
+    Constant *Zero = Constant::getNullValue(Ty);
+    return CmpInst::Create(Instruction::ICmp, I.getPredicate(), And, Zero);
+  }
+
+  return nullptr;
 }
 
 /// Try to fold icmp (binop), X or icmp X, (binop).
@@ -4105,7 +4121,7 @@
   if (!BO0 && !BO1)
     return nullptr;
 
-  if (Instruction *NewICmp = foldICmpXNegX(I))
+  if (Instruction *NewICmp = foldICmpXNegX(I, Builder))
     return NewICmp;
 
   const CmpInst::Predicate Pred = I.getPredicate();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D145846.504357.patch
Type: text/x-patch
Size: 3345 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230311/eedb3dd5/attachment.bin>


More information about the llvm-commits mailing list