[PATCH] D154126: [InstCombine] Transform (A > 0) | (A < 0) -> zext (A != 0) fold

Hongyu Chen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 29 11:13:27 PDT 2023


XChy created this revision.
XChy added reviewers: spatel, nikic, k-arrows, RKSimon.
XChy added a project: LLVM.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
XChy requested review of this revision.
Herald added a subscriber: llvm-commits.

[InstCombine] Transform (A > 0) | (A < 0) -> zext (A != 0) fold

This extends **foldCastedBitwiseLogic** to handle the similar cases.

Actually, for `(A > B) | (A < B)`, when B != 0, it can be optimized to `zext( A != B )` by **foldAndOrOfICmpsUsingRanges**. 
However, when B = 0, **transformZExtICmp** will transform `zext(A < 0) to i32` into `A << 31`,
which cannot be optimized by **foldAndOrOfICmpsUsingRanges**.

Because I'm new to LLVM and has no concise knowledge about how LLVM decides the order of optimization,
I choose to extend **foldCastedBitwiseLogic** to fold `( A << (X - 1) ) | ((A > 0) zext to iX) -> (A != 0) zext to iX`.

And the equivalent fold follows:

  A << (X - 1) ) | ((A > 0) zext to iX
   -> A < 0 | A > 0
   -> (A != 0) zext to iX

It's proved by alive-tv <https://alive2.llvm.org/ce/z/33HzjE>

Related issue:
(a > b) | (a < b) is not simplified only for the case b=0 <https://github.com/llvm/llvm-project/issues/62586>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154126

Files:
  llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  llvm/test/Transforms/InstCombine/and-or-icmps.ll


Index: llvm/test/Transforms/InstCombine/and-or-icmps.ll
===================================================================
--- llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -2571,10 +2571,8 @@
 
 define i32 @icmp_slt_0_or_icmp_sgt_0_i32(i32 %x) {
 ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i32(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i32 [[X:%.*]], 0
-; CHECK-NEXT:    [[X_LOBIT:%.*]] = lshr i32 [[X]], 31
-; CHECK-NEXT:    [[D:%.*]] = zext i1 [[B]] to i32
-; CHECK-NEXT:    [[E:%.*]] = or i32 [[X_LOBIT]], [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[E:%.*]] = zext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[E]]
 ;
   %A = icmp slt i32 %x, 0
@@ -2587,10 +2585,8 @@
 
 define i64 @icmp_slt_0_or_icmp_sgt_0_i64(i64 %x) {
 ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i64(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt i64 [[X:%.*]], 0
-; CHECK-NEXT:    [[X_LOBIT:%.*]] = lshr i64 [[X]], 63
-; CHECK-NEXT:    [[D:%.*]] = zext i1 [[B]] to i64
-; CHECK-NEXT:    [[E:%.*]] = or i64 [[X_LOBIT]], [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[X:%.*]], 0
+; CHECK-NEXT:    [[E:%.*]] = zext i1 [[TMP1]] to i64
 ; CHECK-NEXT:    ret i64 [[E]]
 ;
   %A = icmp slt i64 %x, 0
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1712,6 +1712,27 @@
   assert(I.isBitwiseLogicOp() && "Unexpected opcode for bitwise logic folding");
 
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+  // ( A << (X - 1) ) | ((A > 0) zext to iX) <=> A < 0 | A > 0
+  // <=> (A != 0) zext to iX
+  Value *A;
+  ConstantInt *B;
+  ICmpInst::Predicate pred;
+  if (LogicOpc == Instruction::Or &&
+      ((match(Op0, m_LShr(m_Value(A), m_ConstantInt(B))) &&
+        match(Op1, m_ZExt(m_ICmp(pred, m_Specific(A), m_SpecificInt(0))))) ||
+       (match(Op1, m_LShr(m_Value(A), m_ConstantInt(B))) &&
+        match(Op0, m_ZExt(m_ICmp(pred, m_Specific(A), m_SpecificInt(0))))))) {
+    uint64_t X = A->getType()->getIntegerBitWidth();
+    if (pred == ICmpInst::ICMP_SGT && B->getValue() == X - 1 &&
+        A->getType()->isIntegerTy()) {
+      Value *cmp = Builder.CreateICmp(
+          ICmpInst::ICMP_NE, A,
+          Builder.getInt(APInt::getZero(A->getType()->getIntegerBitWidth())));
+      return new ZExtInst(cmp, A->getType());
+    }
+  }
+
   CastInst *Cast0 = dyn_cast<CastInst>(Op0);
   if (!Cast0)
     return nullptr;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D154126.535892.patch
Type: text/x-patch
Size: 2608 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230629/e2a93fca/attachment.bin>


More information about the llvm-commits mailing list