[llvm] [Instsimplify] lshr&icmp adds support for the or instruction (PR #69445)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 18 03:52:21 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: DianQK (DianQK)

<details>
<summary>Changes</summary>

Closes #<!-- -->69333.

---
Full diff: https://github.com/llvm/llvm-project/pull/69445.diff


2 Files Affected:

- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+33-7) 
- (modified) llvm/test/Transforms/InstSimplify/compare.ll (+128) 


``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index b3feb2470e58efd..1665d6d63ab6e34 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3103,6 +3103,23 @@ static Value *simplifyICmpWithConstant(CmpInst::Predicate Pred, Value *LHS,
   return nullptr;
 }
 
+static bool existOrChain(const Value *From, const Value *To) {
+  const Value *LVal;
+  const Value *RVal;
+  SmallVector<const Value *, 10> WorkList;
+  WorkList.push_back(From);
+  while (!WorkList.empty() && WorkList.size() < 16) {
+    From = WorkList.pop_back_val();
+    if (match(From, m_Or(m_Value(LVal), m_Value(RVal)))) {
+      if (LVal == To || RVal == To)
+        return true;
+      WorkList.push_back(LVal);
+      WorkList.push_back(RVal);
+    }
+  }
+  return false;
+}
+
 static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
                                          BinaryOperator *LBO, Value *RHS,
                                          const SimplifyQuery &Q,
@@ -3174,16 +3191,25 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
   }
 
   // x >>u y <=u x --> true.
+  // x >>u y <=u x | z --> true.
   // x >>u y >u  x --> false.
+  // x >>u y >u  x | z --> false.
   // x udiv y <=u x --> true.
+  // x udiv y <=u x | z --> true.
   // x udiv y >u  x --> false.
-  if (match(LBO, m_LShr(m_Specific(RHS), m_Value())) ||
-      match(LBO, m_UDiv(m_Specific(RHS), m_Value()))) {
-    // icmp pred (X op Y), X
-    if (Pred == ICmpInst::ICMP_UGT)
-      return getFalse(ITy);
-    if (Pred == ICmpInst::ICMP_ULE)
-      return getTrue(ITy);
+  // x udiv y >u  x | z --> false.
+  const Value *RHS0;
+  if (match(LBO, m_LShr(m_Value(RHS0), m_Value())) ||
+      match(LBO, m_UDiv(m_Value(RHS0), m_Value()))) {
+    if (RHS0 == RHS || existOrChain(RHS, RHS0)) {
+      // icmp pred (X op Y), X
+      if (Pred == ICmpInst::ICMP_UGT) {
+        return getFalse(ITy);
+      }
+      if (Pred == ICmpInst::ICMP_ULE) {
+        return getTrue(ITy);
+      }
+    }
   }
 
   // If x is nonzero:
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index ac2ebf52ed6296e..75c9a69b26245d4 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -565,6 +565,134 @@ define i1 @lshr7(i32 %X, i32 %Y) {
   ret i1 %C
 }
 
+define i1 @or_lshr1(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_lshr1(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = lshr i32 %X, %Y
+  %B = or i32 %X, %Z
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_lshr2(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_lshr2(
+; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = lshr i32 %X, %Y
+  %B = or i32 %Y, %Z
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_lshr3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr3(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = lshr i32 %X, %Y
+  %B0 = or i32 %X, %Z
+  %B = or i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_lshr4(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr4(
+; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B0:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = lshr i32 %X, %Y
+  %B0 = or i32 %Y, %Z
+  %B = or i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_lshr5(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_lshr5(
+; CHECK-NEXT:    [[A:%.*]] = lshr i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = and i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = lshr i32 %X, %Y
+  %B0 = or i32 %X, %Z
+  %B = and i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_udiv1(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_udiv1(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = udiv i32 %X, %Y
+  %B = or i32 %X, %Z
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_udiv2(i32 %X, i32 %Y, i32 %Z) {
+; CHECK-LABEL: @or_udiv2(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = udiv i32 %X, %Y
+  %B = or i32 %Y, %Z
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_udiv3(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv3(
+; CHECK-NEXT:    ret i1 false
+;
+  %A = udiv i32 %X, %Y
+  %B0 = or i32 %X, %Z
+  %B = or i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_udiv4(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv4(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B0:%.*]] = or i32 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = or i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = udiv i32 %X, %Y
+  %B0 = or i32 %Y, %Z
+  %B = or i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
+define i1 @or_udiv5(i32 %X, i32 %Y, i32 %Z, i32 %Z1) {
+; CHECK-LABEL: @or_udiv5(
+; CHECK-NEXT:    [[A:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B0:%.*]] = or i32 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = and i32 [[B0]], [[Z1:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[B]], [[A]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %A = udiv i32 %X, %Y
+  %B0 = or i32 %X, %Z
+  %B = and i32 %B0, %Z1
+  %C = icmp ult i32 %B, %A
+  ret i1 %C
+}
+
 define i1 @lshr_nonzero_eq(i32 %x) {
 ; CHECK-LABEL: @lshr_nonzero_eq(
 ; CHECK-NEXT:    [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0

``````````

</details>


https://github.com/llvm/llvm-project/pull/69445


More information about the llvm-commits mailing list