[llvm] [InstCombine] optimize unnecessary sext instruction with add + cmp (PR #152291)
Gaurav Dhingra via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 6 03:54:03 PDT 2025
https://github.com/gxyd created https://github.com/llvm/llvm-project/pull/152291
Fixes https://github.com/llvm/llvm-project/issues/130088
>From 7a9089f891b13441c32cfe1ef640ece53f936b4b Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Thu, 24 Jul 2025 10:28:48 +0530
Subject: [PATCH 1/3] [InstCombine][test] add test for sext+add+cmp instruction
---
.../Transforms/InstCombine/sext_for_add_cmp.ll | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
diff --git a/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll b/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
new file mode 100644
index 0000000000000..c89555422f65e
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+define i1 @sext_add_cmp_to_add_cmp(i16 noundef %x) {
+; CHECK-LABEL: define i1 @sext_add_cmp_to_add_cmp(
+; CHECK-SAME: i16 noundef [[X:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X]] to i128
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i128 [[CONV]], 128
+; CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i128 [[ADD]], 256
+; CHECK-NEXT: ret i1 [[OR_COND_I]]
+;
+entry:
+ %conv = sext i16 %x to i128
+ %add = add i128 %conv, 128
+ %or.cond.i = icmp ult i128 %add, 256
+ ret i1 %or.cond.i
+}
>From c0c69342d233ebda240116e58bd8d9724a53c73e Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Wed, 6 Aug 2025 16:19:53 +0530
Subject: [PATCH 2/3] [InstCombine] remove unnecessary sext instruction for
add+cmp
---
.../InstCombine/InstCombineCompares.cpp | 34 +++++++++++++++++++
.../InstCombine/InstCombineInternal.h | 1 +
2 files changed, 35 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 0894ca92086f3..4718992f1183c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6366,6 +6366,36 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
return new ICmpInst(CmpInst::ICMP_SLT, X, Constant::getNullValue(SrcTy));
}
+Instruction *InstCombinerImpl::foldICmpWithSextAndAdd(ICmpInst &ICmp) {
+ Value *X;
+ ConstantInt *Y, *Z;
+ // Match the pattern: icmp ult (add (sext X), Y), Z
+ // where X is a value, Y and Z are integer constants
+ // icmp ult (add(sext(X), Y)), Z -> icmp ult (add(X, Y)), Z
+ if (match(&ICmp, m_SpecificICmp(CmpInst::ICMP_ULT,
+ m_Add(m_SExt(m_Value(X)), m_ConstantInt(Y)),
+ m_ConstantInt(Z)))) {
+ Type *XType = X->getType();
+ if (!XType->isIntegerTy())
+ return nullptr;
+
+ unsigned XBitWidth = XType->getIntegerBitWidth();
+ auto YValue = Y->getSExtValue();
+ auto ZValue = Z->getSExtValue();
+
+ auto MinValue = -(1LL << (XBitWidth - 1));
+ auto MaxValue = (1LL << (XBitWidth - 1)) - 1;
+
+ // // Check if Y and Z fit within X's type without wrapping
+ if (YValue < MinValue || YValue > MaxValue || ZValue < MinValue || ZValue > MaxValue)
+ return nullptr; // Cannot optimize if Y or Z would wrap in X's type
+
+ Value *NewAdd = Builder.CreateAdd(X, ConstantInt::get(XType, YValue));
+ return new ICmpInst(CmpInst::ICMP_ULT, NewAdd, ConstantInt::get(XType, ZValue));
+ }
+ return nullptr;
+}
+
/// Handle icmp (cast x), (cast or constant).
Instruction *InstCombinerImpl::foldICmpWithCastOp(ICmpInst &ICmp) {
// If any operand of ICmp is a inttoptr roundtrip cast then remove it as
@@ -7705,6 +7735,10 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
}
}
+ if (Instruction *Res = foldICmpWithSextAndAdd(I)) {
+ return Res;
+ }
+
// In case of a comparison with two select instructions having the same
// condition, check whether one of the resulting branches can be simplified.
// If so, just compare the other branch and select the appropriate result.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 8c9de862fe8f2..3a8e01c68bdf8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -712,6 +712,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
const APInt &C);
Instruction *foldICmpTruncWithTruncOrExt(ICmpInst &Cmp,
const SimplifyQuery &Q);
+ Instruction *foldICmpWithSextAndAdd(ICmpInst &ICmp);
Instruction *foldICmpAndConstant(ICmpInst &Cmp, BinaryOperator *And,
const APInt &C);
Instruction *foldICmpXorConstant(ICmpInst &Cmp, BinaryOperator *Xor,
>From 154a4a475956053ea10f904b49fd460fd10dc629 Mon Sep 17 00:00:00 2001
From: Gaurav Dhingra <gauravdhingra.gxyd at gmail.com>
Date: Wed, 6 Aug 2025 16:21:30 +0530
Subject: [PATCH 3/3] [InstCombine][test] update tests for sext instruction
optimization
---
llvm/test/Transforms/InstCombine/icmp-add.ll | 5 ++---
llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll | 5 ++---
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 1a41c1f3e1045..df85f5a3caa65 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3259,9 +3259,8 @@ define i1 @zext_range_check_mergable(i8 %x) {
define i1 @sext_range_check_ult(i8 %x) {
; CHECK-LABEL: @sext_range_check_ult(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X:%.*]] to i32
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3
+; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[X:%.*]], -4
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], 3
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
diff --git a/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll b/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
index c89555422f65e..b8617df750abb 100644
--- a/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
+++ b/llvm/test/Transforms/InstCombine/sext_for_add_cmp.ll
@@ -4,9 +4,8 @@ define i1 @sext_add_cmp_to_add_cmp(i16 noundef %x) {
; CHECK-LABEL: define i1 @sext_add_cmp_to_add_cmp(
; CHECK-SAME: i16 noundef [[X:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[X]] to i128
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i128 [[CONV]], 128
-; CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i128 [[ADD]], 256
+; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[X]], 128
+; CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i16 [[TMP0]], 256
; CHECK-NEXT: ret i1 [[OR_COND_I]]
;
entry:
More information about the llvm-commits
mailing list