[PATCH] D144610: [InstCombine] Add transforms for `(icmp upred (or X, Y), X)`

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 3 16:07:47 PST 2023


goldstein.w.n updated this revision to Diff 502302.
goldstein.w.n edited the summary of this revision.
goldstein.w.n added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144610/new/

https://reviews.llvm.org/D144610

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
  llvm/test/Transforms/InstCombine/icmp-of-or-x.ll


Index: llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
===================================================================
--- llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
+++ llvm/test/Transforms/InstCombine/icmp-of-or-x.ll
@@ -8,7 +8,7 @@
 define i1 @or_ugt(i8 %x, i8 %y) {
 ; CHECK-LABEL: @or_ugt(
 ; CHECK-NEXT:    [[XN1:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[XN1]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[XN1]], [[X]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %xn1 = or i8 %x, %y
@@ -19,7 +19,7 @@
 define <2 x i1> @or_ule(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @or_ule(
 ; CHECK-NEXT:    [[XN1:%.*]] = or <2 x i8> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ule <2 x i8> [[XN1]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[XN1]], [[X]]
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %xn1 = or <2 x i8> %x, %y
@@ -70,8 +70,8 @@
 
 define i1 @or_eq_noundef(i8 %x, i8 noundef %y) {
 ; CHECK-LABEL: @or_eq_noundef(
-; CHECK-NEXT:    [[XN1:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[XN1]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], [[Y]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %xn1 = or i8 %x, %y
@@ -92,8 +92,8 @@
 
 define <2 x i1> @or_ne_noundef(<2 x i8> %x, <2 x i8> noundef %y) {
 ; CHECK-LABEL: @or_ne_noundef(
-; CHECK-NEXT:    [[XN1:%.*]] = or <2 x i8> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i8> [[XN1]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i8> [[TMP1]], [[Y]]
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %xn1 = or <2 x i8> %x, %y
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4102,6 +4102,38 @@
       ICmpInst::ICMP_SLT, Op, Constant::getNullValue(Op->getType()), CxtI, DL);
 }
 
+static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
+                                 InstCombinerImpl &IC) {
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
+  bool Op0IsOr = false;
+  if (match(Op0, m_c_Or(m_Specific(Op1), m_Value(A))))
+    Op0IsOr = true;
+  else if (!match(Op1, m_c_Or(m_Specific(Op0), m_Value(A))))
+    return nullptr;
+
+  Value *OrOp = Op0IsOr ? Op0 : Op1;
+  Value *X = Op0IsOr ? Op1 : Op0;
+  const CmpInst::Predicate Pred = I.getPredicate();
+
+  // icmp (X | Y) u<= X --> (X | Y) == X
+  if (Op0IsOr ? Pred == ICmpInst::ICMP_ULE : Pred == ICmpInst::ICMP_UGE)
+    return new ICmpInst(ICmpInst::ICMP_EQ, Op0, Op1);
+
+  // icmp (X | Y) u> X --> (X | Y) != X
+  else if (Op0IsOr ? Pred == ICmpInst::ICMP_UGT : Pred == ICmpInst::ICMP_ULT)
+    return new ICmpInst(ICmpInst::ICMP_NE, Op0, Op1);
+
+  // icmp (X | noundef Y) eq/ne X
+  //    if (X | noundef Y).hasOneUse()
+  //        --> (X & noundef Y) eq/ne noundef Y
+  if (ICmpInst::isEquality(Pred) && OrOp->hasOneUse() &&
+      isGuaranteedNotToBeUndefOrPoison(A, Q.AC, Q.CxtI, Q.DT,
+                                       /*Depth*/ 0))
+    return new ICmpInst(Pred, IC.Builder.CreateAnd(X, A), A);
+
+  return nullptr;
+}
+
 static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
                                   InstCombinerImpl &IC) {
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
@@ -4490,7 +4522,9 @@
                               ConstantExpr::getNeg(RHSC));
   }
 
-  if (Instruction * R = foldICmpXorXX(I, Q, *this))
+  if (Instruction *R = foldICmpXorXX(I, Q, *this))
+    return R;
+  if (Instruction *R = foldICmpOrXX(I, Q, *this))
     return R;
 
   {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D144610.502302.patch
Type: text/x-patch
Size: 3805 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230304/d57f0321/attachment.bin>


More information about the llvm-commits mailing list