[llvm] [X86] Merge BT with a matching BTR/BTS/BTC (PR #193612)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Thu May 7 03:27:31 PDT 2026
================
@@ -56676,6 +56672,111 @@ static SDValue combineAndnp(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+// Strip TRUNCATE/ZERO_EXTEND/ANY_EXTEND wrappers and `and x, C` where C
+// preserves the low log2(BW) bits — these are transparent to BT/BTR/BTS/BTC,
+// which implicitly mask the bit index to log2(BW) bits.
+static SDValue peekThroughBitPosExtTrunc(SDValue V, unsigned BW) {
+ APInt LowBits =
+ APInt::getLowBitsSet(V.getScalarValueSizeInBits(), Log2_32(BW));
+ for (;;) {
+ unsigned Op = V.getOpcode();
+ if (Op == ISD::TRUNCATE || Op == ISD::ZERO_EXTEND ||
+ Op == ISD::ANY_EXTEND) {
+ V = V.getOperand(0);
+ LowBits = LowBits.zextOrTrunc(V.getScalarValueSizeInBits());
+ continue;
+ }
+ if (Op == ISD::AND) {
+ auto *C = dyn_cast<ConstantSDNode>(V.getOperand(1));
+ if (C && LowBits.isSubsetOf(C->getAPIntValue())) {
+ V = V.getOperand(0);
+ continue;
+ }
+ }
+ return V;
+ }
+}
+
+// Try to merge a (X86ISD::BT Src, BitNo) with a sibling bit-modifying op on
+// Src — AND(Src, rotl -2, X), OR(Src, shl 1, X), XOR(Src, shl 1, X) — into a
+// single flag-producing X86ISD::{BTR,BTS,BTC} node. Both BT and BTR/BTS/BTC
+// set CF from the pre-op bit value, so one instruction subsumes the other.
+// Fixes llvm#165291.
+static SDValue combineBTToBitOpFlag(SDNode *N, SelectionDAG &DAG) {
+ SDValue Src = N->getOperand(0);
+ SDValue BitNo = N->getOperand(1);
+ EVT VT = Src.getValueType();
+ SDLoc DL(N);
+
+ // BT is only emitted for legal integer widths (16/32/64); match those.
+ if (VT != MVT::i16 && VT != MVT::i32 && VT != MVT::i64)
+ return SDValue();
+
+ unsigned BW = VT.getScalarSizeInBits();
+ SDValue PeeledBitNo = peekThroughBitPosExtTrunc(BitNo, BW);
+
+ for (SDNode *User : Src->users()) {
+ if (User == N)
+ continue;
+ unsigned UOpc = User->getOpcode();
+ if (UOpc != ISD::AND && UOpc != ISD::OR && UOpc != ISD::XOR)
+ continue;
+ if (User->getValueType(0) != VT)
+ continue;
+
+ // Identify which operand of User is Src; the other is the mask.
+ SDValue UOp0 = User->getOperand(0);
+ SDValue UOp1 = User->getOperand(1);
+ SDValue Mask;
+ if (UOp0 == SDValue(Src.getNode(), Src.getResNo()))
----------------
RKSimon wrote:
Isn't that UOp0 == Src?
https://github.com/llvm/llvm-project/pull/193612
More information about the llvm-commits
mailing list