[llvm] [InstCombine] Add demanded-bits pext handling (PR #205092)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 9 07:10:52 PDT 2026
https://github.com/mygitljf updated https://github.com/llvm/llvm-project/pull/205092
>From 62933db2657cbd831821897fc21479b6b16d1e16 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Mon, 22 Jun 2026 18:01:53 +0000
Subject: [PATCH 1/4] [InstCombine] Add demanded-bits pext handling
---
.../InstCombine/InstCombineCalls.cpp | 3 +
.../InstCombineSimplifyDemanded.cpp | 29 +++++++
llvm/test/Transforms/InstCombine/pext.ll | 79 +++++++++++++++++++
3 files changed, 111 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6992602f54fe9..29618d53fdb75 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2678,6 +2678,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
break;
}
case Intrinsic::pext: {
+ if (SimplifyDemandedInstructionBits(*II))
+ return II;
+
const APInt *MaskC;
if (match(II->getArgOperand(1), m_APInt(MaskC))) {
unsigned MaskIdx, MaskLen;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index cca297a5b8dc2..ed0a2836447f6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1104,6 +1104,35 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
break;
}
+ case Intrinsic::pext: {
+ APInt DemandedMaskRHS(APInt::getAllOnes(BitWidth));
+ if (SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Q, Depth + 1))
+ return I;
+
+ APInt DemandedMaskLHS(BitWidth, 0);
+ unsigned M0 = 0, M1 = 0;
+ for (unsigned I = 0; I != BitWidth; ++I) {
+ if (!RHSKnown.Zero[I]) {
+ APInt Range = APInt::getBitsSet(BitWidth, M0, M1 + 1);
+ if (DemandedMask.intersects(Range))
+ DemandedMaskLHS.setBit(I);
+ }
+
+ if (RHSKnown.One[I])
+ ++M0, ++M1;
+ else if (!RHSKnown.Zero[I])
+ ++M1;
+ }
+
+ if (SimplifyDemandedBits(I, 0, DemandedMaskLHS, LHSKnown, Q, Depth + 1))
+ return I;
+
+ Known = KnownBits::pext(LHSKnown, RHSKnown);
+ KnownBitsComputed = true;
+
+ break;
+ }
+
case Intrinsic::fshr:
case Intrinsic::fshl: {
const APInt *SA;
diff --git a/llvm/test/Transforms/InstCombine/pext.ll b/llvm/test/Transforms/InstCombine/pext.ll
index 135d72ea5c223..6d2a5c4d0da25 100644
--- a/llvm/test/Transforms/InstCombine/pext.ll
+++ b/llvm/test/Transforms/InstCombine/pext.ll
@@ -102,3 +102,82 @@ define i64 @test_pext_64_constant_fold_2() nounwind readnone {
ret i64 %1
}
+define i32 @test_pext_and_constant_supermask_32(i32 %x) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_constant_supermask_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 42)
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %x, 255
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 42)
+ ret i32 %1
+}
+
+define i64 @test_pext_and_constant_supermask_64(i64 %x) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_constant_supermask_64(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.pext.i64(i64 [[X:%.*]], i64 42)
+; CHECK-NEXT: ret i64 [[TMP1]]
+;
+ %and = and i64 %x, 255
+ %1 = tail call i64 @llvm.pext.i64(i64 %and, i64 42)
+ ret i64 %1
+}
+
+define i32 @test_pext_and_known_zero_mask_32(i32 %x, i32 %y) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_known_zero_mask_32(
+; CHECK-NEXT: [[M:%.*]] = and i32 [[Y:%.*]], 42
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %m = and i32 %y, 42
+ %and = and i32 %x, 63
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
+define i32 @test_pext_and_known_zero_mask_multi_use_32(i32 %x, i32 %y) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_known_zero_mask_multi_use_32(
+; CHECK-NEXT: [[M:%.*]] = and i32 [[Y:%.*]], 42
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 63
+; CHECK-NEXT: [[PEXT:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X]], i32 [[M]])
+; CHECK-NEXT: [[USE:%.*]] = add nuw nsw i32 [[AND]], [[PEXT]]
+; CHECK-NEXT: ret i32 [[USE]]
+;
+ %m = and i32 %y, 42
+ %and = and i32 %x, 63
+ %pext = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ %use = add i32 %and, %pext
+ ret i32 %use
+}
+
+define i32 @test_pext_and_constant_mask_32(i32 %x) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_constant_mask_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 42)
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %x, 42
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 42)
+ ret i32 %1
+}
+
+define i32 @test_pext_and_unknown_mask_32(i32 %x, i32 %m) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_unknown_mask_32(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 63
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[AND]], i32 [[M:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %x, 63
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
+define i32 @test_pext_and_partial_demand_32(i32 %x) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_partial_demand_32(
+; CHECK-NEXT: [[PEXT:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 42)
+; CHECK-NEXT: [[USE:%.*]] = and i32 [[PEXT]], 1
+; CHECK-NEXT: ret i32 [[USE]]
+;
+ %and = and i32 %x, 2
+ %pext = tail call i32 @llvm.pext.i32(i32 %and, i32 42)
+ %use = and i32 %pext, 1
+ ret i32 %use
+}
>From f4d248a6f714d0af634dc51bc9793f06f62edb4f Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Thu, 9 Jul 2026 21:15:55 +0000
Subject: [PATCH 2/4] Fold pext same mask
---
.../InstCombine/InstCombineCalls.cpp | 5 +++++
llvm/test/Transforms/InstCombine/pext.ll | 20 +++++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 29618d53fdb75..bf350e3e26cab 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2681,6 +2681,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (SimplifyDemandedInstructionBits(*II))
return II;
+ Value *X;
+ if (match(II->getArgOperand(0),
+ m_c_And(m_Value(X), m_Specific(II->getArgOperand(1)))))
+ return replaceOperand(*II, 0, X);
+
const APInt *MaskC;
if (match(II->getArgOperand(1), m_APInt(MaskC))) {
unsigned MaskIdx, MaskLen;
diff --git a/llvm/test/Transforms/InstCombine/pext.ll b/llvm/test/Transforms/InstCombine/pext.ll
index 6d2a5c4d0da25..0281a7877e71a 100644
--- a/llvm/test/Transforms/InstCombine/pext.ll
+++ b/llvm/test/Transforms/InstCombine/pext.ll
@@ -159,6 +159,26 @@ define i32 @test_pext_and_constant_mask_32(i32 %x) nounwind readnone {
ret i32 %1
}
+define i32 @test_pext_and_same_variable_mask_32(i32 %x, i32 %m) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_same_variable_mask_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %x, %m
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
+define i32 @test_pext_and_same_variable_mask_commuted_32(i32 %x, i32 %m) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_same_variable_mask_commuted_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %m, %x
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
define i32 @test_pext_and_unknown_mask_32(i32 %x, i32 %m) nounwind readnone {
; CHECK-LABEL: @test_pext_and_unknown_mask_32(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 63
>From e8393c3017fa5abcd6848fc56aff2311df672c55 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Thu, 9 Jul 2026 21:30:34 +0000
Subject: [PATCH 3/4] Revert "Fold pext same mask"
This reverts commit f4d248a6f714d0af634dc51bc9793f06f62edb4f.
---
.../InstCombine/InstCombineCalls.cpp | 5 -----
llvm/test/Transforms/InstCombine/pext.ll | 20 -------------------
2 files changed, 25 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index bf350e3e26cab..29618d53fdb75 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2681,11 +2681,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (SimplifyDemandedInstructionBits(*II))
return II;
- Value *X;
- if (match(II->getArgOperand(0),
- m_c_And(m_Value(X), m_Specific(II->getArgOperand(1)))))
- return replaceOperand(*II, 0, X);
-
const APInt *MaskC;
if (match(II->getArgOperand(1), m_APInt(MaskC))) {
unsigned MaskIdx, MaskLen;
diff --git a/llvm/test/Transforms/InstCombine/pext.ll b/llvm/test/Transforms/InstCombine/pext.ll
index 0281a7877e71a..6d2a5c4d0da25 100644
--- a/llvm/test/Transforms/InstCombine/pext.ll
+++ b/llvm/test/Transforms/InstCombine/pext.ll
@@ -159,26 +159,6 @@ define i32 @test_pext_and_constant_mask_32(i32 %x) nounwind readnone {
ret i32 %1
}
-define i32 @test_pext_and_same_variable_mask_32(i32 %x, i32 %m) nounwind readnone {
-; CHECK-LABEL: @test_pext_and_same_variable_mask_32(
-; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
-; CHECK-NEXT: ret i32 [[TMP1]]
-;
- %and = and i32 %x, %m
- %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
- ret i32 %1
-}
-
-define i32 @test_pext_and_same_variable_mask_commuted_32(i32 %x, i32 %m) nounwind readnone {
-; CHECK-LABEL: @test_pext_and_same_variable_mask_commuted_32(
-; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
-; CHECK-NEXT: ret i32 [[TMP1]]
-;
- %and = and i32 %m, %x
- %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
- ret i32 %1
-}
-
define i32 @test_pext_and_unknown_mask_32(i32 %x, i32 %m) nounwind readnone {
; CHECK-LABEL: @test_pext_and_unknown_mask_32(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 63
>From c680ba44b6abc030514a20b7c2279bca3c588c10 Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Thu, 9 Jul 2026 22:12:48 +0000
Subject: [PATCH 4/4] Handle pext same mask
---
.../InstCombineSimplifyDemanded.cpp | 7 +++++++
llvm/test/Transforms/InstCombine/pext.ll | 20 +++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index ed0a2836447f6..46894546ef411 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1109,6 +1109,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
if (SimplifyDemandedBits(I, 1, DemandedMaskRHS, RHSKnown, Q, Depth + 1))
return I;
+ Value *X;
+ if (match(I->getOperand(0),
+ m_c_And(m_Value(X), m_Specific(I->getOperand(1))))) {
+ replaceOperand(*I, 0, X);
+ return I;
+ }
+
APInt DemandedMaskLHS(BitWidth, 0);
unsigned M0 = 0, M1 = 0;
for (unsigned I = 0; I != BitWidth; ++I) {
diff --git a/llvm/test/Transforms/InstCombine/pext.ll b/llvm/test/Transforms/InstCombine/pext.ll
index 6d2a5c4d0da25..0281a7877e71a 100644
--- a/llvm/test/Transforms/InstCombine/pext.ll
+++ b/llvm/test/Transforms/InstCombine/pext.ll
@@ -159,6 +159,26 @@ define i32 @test_pext_and_constant_mask_32(i32 %x) nounwind readnone {
ret i32 %1
}
+define i32 @test_pext_and_same_variable_mask_32(i32 %x, i32 %m) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_same_variable_mask_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %x, %m
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
+define i32 @test_pext_and_same_variable_mask_commuted_32(i32 %x, i32 %m) nounwind readnone {
+; CHECK-LABEL: @test_pext_and_same_variable_mask_commuted_32(
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.pext.i32(i32 [[X:%.*]], i32 [[M:%.*]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+ %and = and i32 %m, %x
+ %1 = tail call i32 @llvm.pext.i32(i32 %and, i32 %m)
+ ret i32 %1
+}
+
define i32 @test_pext_and_unknown_mask_32(i32 %x, i32 %m) nounwind readnone {
; CHECK-LABEL: @test_pext_and_unknown_mask_32(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 63
More information about the llvm-commits
mailing list