[llvm] b80f31c - [InstSimplify] with logical ops: (X | Y) ? 0 : X --> 0

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 25 06:52:41 PDT 2023


Author: Zhongyunde
Date: 2023-04-25T21:51:41+08:00
New Revision: b80f31c48d63743ece1062f30d5f747a03ee5695

URL: https://github.com/llvm/llvm-project/commit/b80f31c48d63743ece1062f30d5f747a03ee5695
DIFF: https://github.com/llvm/llvm-project/commit/b80f31c48d63743ece1062f30d5f747a03ee5695.diff

LOG: [InstSimplify] with logical ops: (X | Y) ? 0 : X --> 0

Use simplifySelectWithICmpEq to handle the implied equalities from the icmp-or,
then both of ICMP_NE and ICMP_EQ will be addressed
  (X | Y) == 0 ?  X : 0 --> 0 (commuted 2 ways)
  (X | Y) != 0 ?  0 : X --> 0 (commuted 2 ways)
Fixes https://github.com/llvm/llvm-project/issues/62263

Reviewed By: nikic, RKSimon
Differential Revision: https://reviews.llvm.org/D148986

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/select_or_and.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f45ad9829e90..57cfef4e785c 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4436,6 +4436,24 @@ static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
                                Pred == ICmpInst::ICMP_EQ);
 }
 
+/// Try to simplify a select instruction when its condition operand is an
+/// integer equality comparison.
+static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
+                                       Value *TrueVal, Value *FalseVal,
+                                       const SimplifyQuery &Q,
+                                       unsigned MaxRecurse) {
+  if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q,
+                             /* AllowRefinement */ false,
+                             MaxRecurse) == TrueVal)
+    return FalseVal;
+  if (simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q,
+                             /* AllowRefinement */ true,
+                             MaxRecurse) == FalseVal)
+    return FalseVal;
+
+  return nullptr;
+}
+
 /// Try to simplify a select instruction when its condition operand is an
 /// integer comparison.
 static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
@@ -4524,30 +4542,31 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
   // the arms of the select. See if substituting this value into the arm and
   // simplifying the result yields the same value as the other arm.
   if (Pred == ICmpInst::ICMP_EQ) {
-    if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, Q,
-                               /* AllowRefinement */ false,
-                               MaxRecurse) == TrueVal ||
-        simplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, Q,
-                               /* AllowRefinement */ false,
-                               MaxRecurse) == TrueVal)
-      return FalseVal;
-    if (simplifyWithOpReplaced(TrueVal, CmpLHS, CmpRHS, Q,
-                               /* AllowRefinement */ true,
-                               MaxRecurse) == FalseVal ||
-        simplifyWithOpReplaced(TrueVal, CmpRHS, CmpLHS, Q,
-                               /* AllowRefinement */ true,
-                               MaxRecurse) == FalseVal)
-      return FalseVal;
+    if (Value *V = simplifySelectWithICmpEq(CmpLHS, CmpRHS, TrueVal, FalseVal,
+                                            Q, MaxRecurse))
+      return V;
+    if (Value *V = simplifySelectWithICmpEq(CmpRHS, CmpLHS, TrueVal, FalseVal,
+                                            Q, MaxRecurse))
+      return V;
+
+    // select(X | Y == 0 ?  X : 0) --> 0 (commuted 2 ways)
+    Value *X;
+    Value *Y;
+    if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y))) &&
+        match(CmpRHS, m_Zero())) {
+      // X | Y == 0 implies X == 0 and Y == 0.
+      if (Value *V = simplifySelectWithICmpEq(X, CmpRHS, TrueVal, FalseVal, Q,
+                                              MaxRecurse))
+        return V;
+      if (Value *V = simplifySelectWithICmpEq(Y, CmpRHS, TrueVal, FalseVal, Q,
+                                              MaxRecurse))
+        return V;
+    }
   }
 
   if (Pred == ICmpInst::Predicate::ICMP_EQ) {
     Value *X;
     Value *Y;
-    // select(X | Y == 0, X or Y, X | Y) -> X | Y
-    if (match(CondVal, m_ICmp(Pred, m_Specific(FalseVal), m_Zero())) &&
-        match(FalseVal, m_Or(m_Value(X), m_Value(Y))) &&
-        (TrueVal == X || TrueVal == Y))
-      return FalseVal;
     // select(X & Y == -1, X or Y, X & Y) -> X & Y
     if (match(CondVal, m_ICmp(Pred, m_Specific(FalseVal), m_AllOnes())) &&
         match(FalseVal, m_And(m_Value(X), m_Value(Y))) &&

diff  --git a/llvm/test/Transforms/InstSimplify/select_or_and.ll b/llvm/test/Transforms/InstSimplify/select_or_and.ll
index 63476e2483aa..fcac90be6b3f 100644
--- a/llvm/test/Transforms/InstSimplify/select_or_and.ll
+++ b/llvm/test/Transforms/InstSimplify/select_or_and.ll
@@ -64,10 +64,7 @@ define <4 x i32> @select_or_vec(<4 x i32> %x, <4 x i32> %y) {
 ; select(Y | X == 0, Y | X, Y)
 define i32 @select_or_not_1(i32 %x, i32 %y) {
 ; CHECK-LABEL: @select_or_not_1(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[Y]]
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
 ;
   %or = or i32 %y, %x
   %cmp = icmp eq i32 %or, 0
@@ -77,10 +74,7 @@ define i32 @select_or_not_1(i32 %x, i32 %y) {
 ; select(Y | X != 0, Y, Y | X)
 define i32 @select_or_not_2(i32 %x, i32 %y) {
 ; CHECK-LABEL: @select_or_not_2(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[OR]], 0
-; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]]
-; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK-NEXT:    ret i32 [[Y:%.*]]
 ;
   %or = or i32 %y, %x
   %cmp = icmp ne i32 %or, 0
@@ -209,10 +203,7 @@ define i32 @select_icmp_and_eq(i32 %a, i32 %b) {
 ; https://alive2.llvm.org/ce/z/hSyCuR
 define i32 @select_icmp_or_eq(i32 %a, i32 %b) {
 ; CHECK-LABEL: @select_icmp_or_eq(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[A]], i32 0
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %or = or i32 %a, %b
   %tobool = icmp eq i32 %or, 0
@@ -222,10 +213,7 @@ define i32 @select_icmp_or_eq(i32 %a, i32 %b) {
 
 define i32 @select_icmp_or_eq_commuted(i32 %a, i32 %b) {
 ; CHECK-LABEL: @select_icmp_or_eq_commuted(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[OR]], 0
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[B]], i32 0
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %or = or i32 %a, %b
   %tobool = icmp eq i32 %or, 0
@@ -236,10 +224,7 @@ define i32 @select_icmp_or_eq_commuted(i32 %a, i32 %b) {
 ; https://alive2.llvm.org/ce/z/S_pQek
 define <2 x i16> @select_icmp_or_eq_vec(<2 x i16> %a, <2 x i16> %b) {
 ; CHECK-LABEL: @select_icmp_or_eq_vec(
-; CHECK-NEXT:    [[OR:%.*]] = or <2 x i16> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq <2 x i16> [[OR]], zeroinitializer
-; CHECK-NEXT:    [[COND:%.*]] = select <2 x i1> [[TOBOOL]], <2 x i16> [[A]], <2 x i16> zeroinitializer
-; CHECK-NEXT:    ret <2 x i16> [[COND]]
+; CHECK-NEXT:    ret <2 x i16> zeroinitializer
 ;
   %or = or <2 x i16> %a, %b
   %tobool = icmp eq <2 x i16> %or, <i16 0, i16 0>
@@ -250,10 +235,7 @@ define <2 x i16> @select_icmp_or_eq_vec(<2 x i16> %a, <2 x i16> %b) {
 ; The ne will also be matched
 define i32 @select_icmp_or_ne(i32 %a, i32 %b) {
 ; CHECK-LABEL: @select_icmp_or_ne(
-; CHECK-NEXT:    [[OR:%.*]] = or i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[OR]], 0
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 0, i32 [[A]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    ret i32 0
 ;
   %or = or i32 %a, %b
   %tobool = icmp ne i32 %or, 0


        


More information about the llvm-commits mailing list