[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