[llvm] [X86] computeKnownBitsForTargetNode - extend X86ISD::BZHI handling. Fixes 177364. (PR #179444)

Shamshura Egor via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 3 06:46:58 PST 2026


https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/179444

>From 5eb46a7b6b12a8c602bb95d58c9569a80906624f Mon Sep 17 00:00:00 2001
From: Shamshura Egor <shamshuraegor at gmail.com>
Date: Tue, 3 Feb 2026 10:57:21 +0000
Subject: [PATCH 1/4] Added MinValue check.

---
 llvm/lib/Target/X86/X86ISelLowering.cpp |  4 ++++
 llvm/test/CodeGen/X86/combine-bzhi.ll   | 19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 15f0815fe4e06..6afd685475007 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -39298,6 +39298,10 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
       }
     }
 
+    APInt MaskMinValue = Known2.getMinValue();
+    if (MaskMinValue.uge(BitWidth))
+      break;
+
     // Zeros are retained from the src operand. But not necessarily ones.
     Known.One.clearAllBits();
     break;
diff --git a/llvm/test/CodeGen/X86/combine-bzhi.ll b/llvm/test/CodeGen/X86/combine-bzhi.ll
index 54e76469dbb82..6f719b03b0307 100644
--- a/llvm/test/CodeGen/X86/combine-bzhi.ll
+++ b/llvm/test/CodeGen/X86/combine-bzhi.ll
@@ -40,3 +40,22 @@ define i64 @test_bzhi64_constfold() nounwind readnone {
   ret i64 %1
 }
 
+define i32 @test_bzhi32_minvaluefold(i32 %arg) nounwind readnone {
+; CHECK-LABEL: test_bzhi32_minvaluefold:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl $5, %eax
+; CHECK-NEXT:    retq
+  %2 = or i32 %arg, 32
+  %3 = tail call i32 @llvm.x86.bmi.bzhi.32(i32 5, i32 %2)
+  ret i32 %3
+}
+
+define i64 @test_bzhi64_minvaluefold(i64 %arg) nounwind readnone {
+; CHECK-LABEL: test_bzhi64_minvaluefold:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl $5, %eax
+; CHECK-NEXT:    retq
+  %2 = or i64 %arg, 64
+  %3 = tail call i64 @llvm.x86.bmi.bzhi.64(i64 5, i64 %2)
+  ret i64 %3
+}

>From 5baeacb9ce188a39232a6ae9319c3894728012d1 Mon Sep 17 00:00:00 2001
From: Shamshura Egor <shamshuraegor at gmail.com>
Date: Tue, 3 Feb 2026 11:38:20 +0000
Subject: [PATCH 2/4] Added MinValue-MaxValue range check.

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 12 ++++++++++++
 llvm/test/CodeGen/X86/combine-bzhi.ll   | 22 ++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6afd685475007..e1dc6497fb8a5 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -39302,6 +39302,18 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
     if (MaskMinValue.uge(BitWidth))
       break;
 
+    APInt MaskMaxValue = Known2.getMaxValue();
+    if (MaskMaxValue.ult(BitWidth)) {
+      auto MinValue = MaskMinValue.getZExtValue();
+      auto MaxValue = MaskMaxValue.getZExtValue();
+      Known.One.clearBits(MaxValue, BitWidth);
+      Known.Zero.setBits(MaxValue, BitWidth);
+
+      Known.One.clearBits(MinValue, MaxValue);
+      if (Known.isConstant())
+        break;
+    }
+
     // Zeros are retained from the src operand. But not necessarily ones.
     Known.One.clearAllBits();
     break;
diff --git a/llvm/test/CodeGen/X86/combine-bzhi.ll b/llvm/test/CodeGen/X86/combine-bzhi.ll
index 6f719b03b0307..3a1d4325c7523 100644
--- a/llvm/test/CodeGen/X86/combine-bzhi.ll
+++ b/llvm/test/CodeGen/X86/combine-bzhi.ll
@@ -59,3 +59,25 @@ define i64 @test_bzhi64_minvaluefold(i64 %arg) nounwind readnone {
   %3 = tail call i64 @llvm.x86.bmi.bzhi.64(i64 5, i64 %2)
   ret i64 %3
 }
+
+define i32 @test_bzhi32_range(i32 %arg) nounwind readnone {
+; CHECK-LABEL: test_bzhi32_range:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl $42, %eax
+; CHECK-NEXT:    retq
+  %2 = or i32 %arg, 6
+  %3 = and i32 %2, 7
+  %4 = tail call i32 @llvm.x86.bmi.bzhi.32(i32 699050, i32 %3)
+  ret i32 %4
+}
+
+define i64 @test_bzhi64_range(i64 %arg) nounwind readnone {
+; CHECK-LABEL: test_bzhi64_range:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movl $42, %eax
+; CHECK-NEXT:    retq
+  %2 = or i64 %arg, 6
+  %3 = and i64 %2, 7
+  %4 = tail call i64 @llvm.x86.bmi.bzhi.64(i64 699050, i64 %3)
+  ret i64 %4
+}

>From 2177e773b2e7923829476ff22dd9ff266e9a81d0 Mon Sep 17 00:00:00 2001
From: Shamshura Egor <shamshuraegor at gmail.com>
Date: Tue, 3 Feb 2026 12:01:40 +0000
Subject: [PATCH 3/4] Improved range check.

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index e1dc6497fb8a5..181ca7a8db949 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -39310,8 +39310,7 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
       Known.Zero.setBits(MaxValue, BitWidth);
 
       Known.One.clearBits(MinValue, MaxValue);
-      if (Known.isConstant())
-        break;
+      break;
     }
 
     // Zeros are retained from the src operand. But not necessarily ones.

>From 0a490e60ca4e23921efea6455129ee4d51972230 Mon Sep 17 00:00:00 2001
From: Shamshura Egor <shamshuraegor at gmail.com>
Date: Tue, 3 Feb 2026 14:46:23 +0000
Subject: [PATCH 4/4] Added comments. Removed auto.

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 181ca7a8db949..c4e9f662e2953 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -39286,7 +39286,6 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
 
     // If the mask control (lower 8 bits) is less than the bitwidth, then the
     // upper bits are set to zero: dst[BW:IMM8] = 0
-    // TODO: Generalise this to use Known2 getMinValue() + getMaxValue().
     Known2 = Known2.trunc(8);
     if (Known2.isConstant()) {
       uint64_t Mask = Known2.getConstant().getZExtValue();
@@ -39298,14 +39297,20 @@ void X86TargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
       }
     }
 
+    // If the mask control minimum value is >= bitwidth, 
+    // the src knownbits are valid and can be returned 
     APInt MaskMinValue = Known2.getMinValue();
     if (MaskMinValue.uge(BitWidth))
       break;
 
+    // If the mask control maximum value is < bitwidth,
+    // all src knownbits above maximum value are cleared to zero
+    // all src knownbits below minimum value stay
+    // in between only src known zero bits remain
     APInt MaskMaxValue = Known2.getMaxValue();
     if (MaskMaxValue.ult(BitWidth)) {
-      auto MinValue = MaskMinValue.getZExtValue();
-      auto MaxValue = MaskMaxValue.getZExtValue();
+      uint64_t MinValue = MaskMinValue.getZExtValue();
+      uint64_t MaxValue = MaskMaxValue.getZExtValue();
       Known.One.clearBits(MaxValue, BitWidth);
       Known.Zero.setBits(MaxValue, BitWidth);
 



More information about the llvm-commits mailing list