[llvm] [InstCombine] Fold `(x < 2^32) & (trunc(x to i32) == 0)` into `x == 0` (PR #171195)
Tirthankar Mazumder via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 11 10:53:30 PST 2025
https://github.com/wermos updated https://github.com/llvm/llvm-project/pull/171195
>From 16b12d3fcfbcef7f15c984d9260b4ff4aa473b9e Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Fri, 12 Dec 2025 00:21:49 +0530
Subject: [PATCH 1/2] Pre-commit tests
---
.../InstCombine/InstCombineCompares.cpp | 2 +-
llvm/test/Transforms/InstCombine/and-or-icmps.ll | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 616cb04be9dbc..911bc95ac7700 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6291,7 +6291,7 @@ Instruction *InstCombinerImpl::foldICmpWithTrunc(ICmpInst &ICmp) {
// This matches patterns corresponding to tests of the signbit as well as:
// (trunc X) pred C2 --> (X & Mask) == C
if (auto Res = decomposeBitTestICmp(Op0, Op1, Pred, /*LookThroughTrunc=*/true,
- /*AllowNonZeroC=*/true)) {
+ /*AllowNonZeroC=*/true, /*DecomposeAnd=*/true)) {
Value *And = Builder.CreateAnd(Res->X, Res->Mask);
Constant *C = ConstantInt::get(Res->X->getType(), Res->C);
return new ICmpInst(Res->Pred, And, C);
diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 290e344acb980..bd62e7726b629 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -3721,3 +3721,19 @@ define i1 @merge_range_check_or(i8 %a) {
%and = or i1 %cmp1, %cmp2
ret i1 %and
}
+
+; Just a very complicated way of checking if v1 == 0.
+define i1 @complicated_zero_equality_test(i64 %v1) {
+; CHECK-LABEL: @complicated_zero_equality_test(
+; CHECK-NEXT: [[V2:%.*]] = trunc i64 [[V1:%.*]] to i32
+; CHECK-NEXT: [[V3:%.*]] = icmp eq i32 [[V2]], 0
+; CHECK-NEXT: [[V4:%.*]] = icmp ult i64 [[V1]], 4294967296
+; CHECK-NEXT: [[V5:%.*]] = and i1 [[V4]], [[V3]]
+; CHECK-NEXT: ret i1 [[V5]]
+;
+ %v2 = trunc i64 %v1 to i32
+ %v3 = icmp eq i32 %v2, 0
+ %v4 = icmp ult i64 %v1, 4294967296 ; 2 ^ 32
+ %v5 = and i1 %v4, %v3
+ ret i1 %v5
+}
>From 566242fddb79458e07a91f3847adcafee4ff3c35 Mon Sep 17 00:00:00 2001
From: Tirthankar Mazumder <tmazumder.github at gmail.com>
Date: Fri, 12 Dec 2025 00:22:47 +0530
Subject: [PATCH 2/2] Implement missing optimization in `decompostBitTestICmp`.
---
llvm/lib/Analysis/CmpInstAnalysis.cpp | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Analysis/CmpInstAnalysis.cpp b/llvm/lib/Analysis/CmpInstAnalysis.cpp
index a6d0d3ff4fcd4..c6bd538a9fe7a 100644
--- a/llvm/lib/Analysis/CmpInstAnalysis.cpp
+++ b/llvm/lib/Analysis/CmpInstAnalysis.cpp
@@ -153,15 +153,26 @@ llvm::decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate Pred,
case ICmpInst::ICMP_NE: {
assert(DecomposeAnd);
const APInt *AndC;
- Value *AndVal;
- if (match(LHS, m_And(m_Value(AndVal), m_APIntAllowPoison(AndC)))) {
- LHS = AndVal;
+ Value *X;
+
+ if (match(LHS, m_And(m_Value(X), m_APIntAllowPoison(AndC)))) {
+ LHS = X;
Result.Mask = *AndC;
Result.C = C;
Result.Pred = Pred;
break;
}
+ // Try to convert (trunc X) eq/ne C into (X & Mask) eq/ne C
+ if (LookThroughTrunc && match(LHS, m_Trunc(m_Value(X)))) {
+ Result.X = X;
+ Result.Pred = Pred;
+ unsigned BitWidth = X->getType()->getScalarSizeInBits();
+ Result.Mask = APInt::getLowBitsSet(BitWidth, C.getBitWidth());
+ Result.C = C.zext(BitWidth);
+ break;
+ }
+
return std::nullopt;
}
}
More information about the llvm-commits
mailing list