[llvm] [InstCombine] Eliminate icmp+zext pairs over phis more aggressively (PR #121767)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 6 06:48:23 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
When folding icmp over phi, add a special case for `icmp eq (zext(bool), 0)`, which is known to fold to `!bool` and thus won't increase the instruction count. This helps convert more phis to i1, esp. in loops.
This is based on existing logic we have to support this for icmp of ucmp/scmp.
---
Full diff: https://github.com/llvm/llvm-project/pull/121767.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+23-6)
- (modified) llvm/test/Transforms/InstCombine/phi.ll (+5-6)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index f63de1f0d410e2..553435c937a70a 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1822,12 +1822,29 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN,
continue;
}
- // If the only use of phi is comparing it with a constant then we can
- // put this comparison in the incoming BB directly after a ucmp/scmp call
- // because we know that it will simplify to a single icmp.
- const APInt *Ignored;
- if (isa<CmpIntrinsic>(InVal) && InVal->hasOneUser() &&
- match(&I, m_ICmp(m_Specific(PN), m_APInt(Ignored)))) {
+ // Handle some cases that can't be fully simplified, but where we know that
+ // the two instructions will fold into one.
+ auto WillFold = [&]() {
+ if (!InVal->hasOneUser())
+ return false;
+
+ // icmp of ucmp/scmp with constant will fold to icmp.
+ const APInt *Ignored;
+ if (isa<CmpIntrinsic>(InVal) &&
+ match(&I, m_ICmp(m_Specific(PN), m_APInt(Ignored))))
+ return true;
+
+ // icmp eq zext(bool), 0 will fold to !bool.
+ if (isa<ZExtInst>(InVal) &&
+ cast<ZExtInst>(InVal)->getSrcTy()->isIntOrIntVectorTy(1) &&
+ match(&I,
+ m_SpecificICmp(ICmpInst::ICMP_EQ, m_Specific(PN), m_Zero())))
+ return true;
+
+ return false;
+ };
+
+ if (WillFold()) {
OpsToMoveUseToIncomingBB.push_back(i);
NewPhiValues.push_back(nullptr);
continue;
diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll
index 33849291d832fc..4756b4f30e5606 100644
--- a/llvm/test/Transforms/InstCombine/phi.ll
+++ b/llvm/test/Transforms/InstCombine/phi.ll
@@ -2828,13 +2828,13 @@ define i1 @test_zext_icmp_eq_0(i1 %a, i1 %b, i32 %c) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[A:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
-; CHECK-NEXT: [[B_EXT:%.*]] = zext i1 [[B:%.*]] to i32
+; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[B:%.*]], true
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: else:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[C:%.*]], 0
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
-; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[B_EXT]], [[IF]] ], [ [[C:%.*]], [[ELSE]] ]
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[PHI]], 0
+; CHECK-NEXT: [[CMP:%.*]] = phi i1 [ [[TMP0]], [[IF]] ], [ [[TMP1]], [[ELSE]] ]
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
@@ -2916,10 +2916,9 @@ define i1 @test_zext_icmp_eq_0_loop(i1 %c, i1 %b) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[EXT:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[X:%.*]] = icmp eq i32 [[PHI]], 0
+; CHECK-NEXT: [[X:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[Y:%.*]] = and i1 [[X]], [[B:%.*]]
-; CHECK-NEXT: [[EXT]] = zext i1 [[Y]] to i32
+; CHECK-NEXT: [[TMP0]] = xor i1 [[Y]], true
; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i1 [[X]]
``````````
</details>
https://github.com/llvm/llvm-project/pull/121767
More information about the llvm-commits
mailing list