[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