[llvm] [X86] LowerAndToBT - convert to SDPatternMatch (PR #181696)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 16 08:23:07 PST 2026
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/181696
Fixes an issue where a partial pattern (and then early-out) prevented a later match
Prep work for #147216
>From 15f8b057b71db8cad61160a8f58646f5bea35c9c Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 16 Feb 2026 16:19:57 +0000
Subject: [PATCH] [X86] LowerAndToBT - convert to SDPatternMatch
Fixes an issue where a partial pattern (and then early-out) prevented a later match
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 80 ++++++++-----------
...st-and-by-const-from-lshr-in-eqcmp-zero.ll | 8 +-
2 files changed, 38 insertions(+), 50 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index d63840267cf5f..35bf2cfee9d68 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -24365,55 +24365,43 @@ X86TargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
/// Returns the BT node and the condition code needed to use it.
static SDValue LowerAndToBT(SDValue And, ISD::CondCode CC, const SDLoc &dl,
SelectionDAG &DAG, X86::CondCode &X86CC) {
+ using namespace SDPatternMatch;
assert(And.getOpcode() == ISD::AND && "Expected AND node!");
- SDValue Op0 = And.getOperand(0);
- SDValue Op1 = And.getOperand(1);
- if (Op0.getOpcode() == ISD::TRUNCATE)
- Op0 = Op0.getOperand(0);
- if (Op1.getOpcode() == ISD::TRUNCATE)
- Op1 = Op1.getOperand(0);
-
- SDValue Src, BitNo;
- if (Op1.getOpcode() == ISD::SHL)
- std::swap(Op0, Op1);
- if (Op0.getOpcode() == ISD::SHL) {
- if (isOneConstant(Op0.getOperand(0))) {
- // If we looked past a truncate, check that it's only truncating away
- // known zeros.
- unsigned BitWidth = Op0.getValueSizeInBits();
- unsigned AndBitWidth = And.getValueSizeInBits();
- if (BitWidth > AndBitWidth) {
- KnownBits Known = DAG.computeKnownBits(Op0);
- if (Known.countMinLeadingZeros() < BitWidth - AndBitWidth)
- return SDValue();
- }
- Src = Op1;
- BitNo = Op0.getOperand(1);
- }
- } else if (Op1.getOpcode() == ISD::Constant) {
- ConstantSDNode *AndRHS = cast<ConstantSDNode>(Op1);
- uint64_t AndRHSVal = AndRHS->getZExtValue();
- SDValue AndLHS = Op0;
-
- if (AndRHSVal == 1 && AndLHS.getOpcode() == ISD::SRL) {
- Src = AndLHS.getOperand(0);
- BitNo = AndLHS.getOperand(1);
- } else {
- // Use BT if the immediate can't be encoded in a TEST instruction or we
- // are optimizing for size and the immedaite won't fit in a byte.
- bool OptForSize = DAG.shouldOptForSize();
- if ((!isUInt<32>(AndRHSVal) || (OptForSize && !isUInt<8>(AndRHSVal))) &&
- isPowerOf2_64(AndRHSVal)) {
- Src = AndLHS;
- BitNo = DAG.getConstant(Log2_64_Ceil(AndRHSVal), dl,
- Src.getValueType());
- }
+ assert(And.getValueType().isScalarInteger() && "Scalar type expected");
+
+ APInt AndRHSVal;
+ SDValue Shl, Src, BitNo;
+ if (sd_match(And,
+ m_And(m_TruncOrSelf(m_Value(Src)),
+ m_TruncOrSelf(m_AllOf(m_Value(Shl),
+ m_Shl(m_One(), m_Value(BitNo))))))) {
+ // If we looked past a truncate, check that it's only truncating away known
+ // zeros.
+ unsigned BitWidth = Shl.getValueSizeInBits();
+ unsigned AndBitWidth = And.getValueSizeInBits();
+ if (BitWidth > AndBitWidth) {
+ KnownBits Known = DAG.computeKnownBits(Shl);
+ if (Known.countMinLeadingZeros() < (BitWidth - AndBitWidth))
+ return SDValue();
}
- }
-
- // No patterns found, give up.
- if (!Src.getNode())
+ } else if (sd_match(And,
+ m_And(m_TruncOrSelf(m_Srl(m_Value(Src), m_Value(BitNo))),
+ m_One()))) {
+ // ((Src >> BitNo) & 1) ==/!= 0
+ } else if (sd_match(And, m_And(m_TruncOrSelf(m_Value(Src)),
+ m_ConstInt(AndRHSVal)))) {
+ // Use BT if the immediate can't be encoded in a TEST instruction or we
+ // are optimizing for size and the immediate won't fit in a byte.
+ bool OptForSize = DAG.shouldOptForSize();
+ if (!AndRHSVal.isPowerOf2() ||
+ (AndRHSVal.isIntN(32) && (!OptForSize || AndRHSVal.isIntN(8))))
+ return SDValue();
+ // (Src & ConstPow2) ==/!= 0
+ BitNo = DAG.getConstant(AndRHSVal.ceilLogBase2(), dl, Src.getValueType());
+ } else {
+ // No patterns found, give up.
return SDValue();
+ }
// Remove any bit flip.
if (isBitwiseNot(Src)) {
diff --git a/llvm/test/CodeGen/X86/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll b/llvm/test/CodeGen/X86/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
index 9121cf2d654a3..63302b41e2076 100644
--- a/llvm/test/CodeGen/X86/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
+++ b/llvm/test/CodeGen/X86/hoist-and-by-const-from-lshr-in-eqcmp-zero.ll
@@ -366,15 +366,15 @@ define i1 @scalar_i64_signbit_eq(i64 %x, i64 %y) nounwind {
; X64-BMI1-NEXT: movq %rsi, %rcx
; X64-BMI1-NEXT: # kill: def $cl killed $cl killed $rcx
; X64-BMI1-NEXT: shlq %cl, %rdi
-; X64-BMI1-NEXT: shrq $63, %rdi
-; X64-BMI1-NEXT: sete %al
+; X64-BMI1-NEXT: btq $63, %rdi
+; X64-BMI1-NEXT: setae %al
; X64-BMI1-NEXT: retq
;
; X64-BMI2-LABEL: scalar_i64_signbit_eq:
; X64-BMI2: # %bb.0:
; X64-BMI2-NEXT: shlxq %rsi, %rdi, %rax
-; X64-BMI2-NEXT: shrq $63, %rax
-; X64-BMI2-NEXT: sete %al
+; X64-BMI2-NEXT: btq $63, %rax
+; X64-BMI2-NEXT: setae %al
; X64-BMI2-NEXT: retq
%t0 = lshr i64 9223372036854775808, %y
%t1 = and i64 %t0, %x
More information about the llvm-commits
mailing list