Skip to content

Commit aac70ed

Browse files
committed
[X86] Distribute Certain Bitwise Operations over SELECT
InstCombine canonicalizes `(select P (and X (- X)) X)` to `(and (select P (- X) umax) X)`. This is counterproductive for the X86 backend when BMI is available because we can encode `(and X (- X))` using the `BLSI` instruction. A similar situation arises if we have `(select P (and X (sub X 1)) X)` (prevents use of `BLSR` instruction) or `(select P (xor X (sub X 1)) X)` (prevents use of `BLSMSK` instruction). Trigger the inverse transformation in the X86 backend if BMI is available and we can use the mentioned BMI instructions. This is done by adjusting the `shouldFoldSelectWithIdentityConstant()` implementation for the X86 backend. In this way, we get `(select P (and X (- X)) X)` again, which enables the use of `BLSI` (similar for the other cases described above). Alive proofs: https://alive2.llvm.org/ce/z/MT_pKi Fixes #131587, fixes #133848.
1 parent 072dfa6 commit aac70ed

File tree

2 files changed

+228
-521
lines changed

2 files changed

+228
-521
lines changed

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35552,8 +35552,29 @@ bool X86TargetLowering::isNarrowingProfitable(SDNode *N, EVT SrcVT,
3555235552
bool X86TargetLowering::shouldFoldSelectWithIdentityConstant(
3555335553
unsigned BinOpcode, EVT VT, unsigned SelectOpcode, SDValue X,
3555435554
SDValue Y) const {
35555-
if (SelectOpcode != ISD::VSELECT)
35555+
if (SelectOpcode == ISD::SELECT) {
35556+
if (VT.isVector())
35557+
return false;
35558+
if (!Subtarget.hasBMI() || (VT != MVT::i32 && VT != MVT::i64))
35559+
return false;
35560+
using namespace llvm::SDPatternMatch;
35561+
// BLSI
35562+
if (BinOpcode == ISD::AND && (sd_match(Y, m_Neg(m_Specific(X))) ||
35563+
sd_match(X, m_Neg(m_Specific(Y)))))
35564+
return true;
35565+
// BLSR
35566+
if (BinOpcode == ISD::AND &&
35567+
(sd_match(Y, m_Add(m_Specific(X), m_AllOnes())) ||
35568+
sd_match(X, m_Add(m_Specific(Y), m_AllOnes()))))
35569+
return true;
35570+
// BLSMSK
35571+
if (BinOpcode == ISD::XOR &&
35572+
(sd_match(Y, m_Add(m_Specific(X), m_AllOnes())) ||
35573+
sd_match(X, m_Add(m_Specific(Y), m_AllOnes()))))
35574+
return true;
35575+
3555635576
return false;
35577+
}
3555735578
// TODO: This is too general. There are cases where pre-AVX512 codegen would
3555835579
// benefit. The transform may also be profitable for scalar code.
3555935580
if (!Subtarget.hasAVX512())

0 commit comments

Comments
 (0)