[llvm] [DAG][X86] Bitfield insertion can combine into SHL + SHRD (PR #220182)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 06:57:59 PDT 2026


================
@@ -8867,6 +8867,49 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1,
   return SDValue();
 }
 
+// Fold an OR with a masked destination and a left-shifted
+// source into a shift + double-precision shift (SHRD):
+//
+// fold: (or (and X, Mask), (shl Y, MaskBitNum)) -> (fshr X, (shl Y,
+// (MaxWideNumBits - MaskBitNum)))
+static SDValue combineOrOnSHLToFSHR(SDNode *N, const SDLoc &DL,
+                                    SelectionDAG &DAG) {
+  EVT VT = N->getValueType(0);
+
+  APInt Mask, ShiftAmount;
+  SDValue X, Y;
+
+  // Check for the following pattern:
+  //   (or (and X, HighBitsMask(C)), (srl Y, C))
+  // Do not combine if there are multi-use AND and OR.
+  // It does not result in more performant code.
+  if (!sd_match(N, m_Or(m_OneUse(m_And(m_Value(X), m_ConstInt(Mask))),
+                        m_OneUse(m_Shl(m_Value(Y), m_ConstInt(ShiftAmount))))))
+    return SDValue();
+
+  // Max bit-width of operands
+  uint64_t MaxMaskBitWidth = VT.getScalarSizeInBits();
+
+  // Check for Mask and ShiftAmount
+  //
+  // (shl Y, ShiftAmount) fills the top (MaxMaskBitWidth - ShiftAmount) bits,
+  // so X must keep exactly the low ShiftAmount.
+  if (!(ShiftAmount.ugt(0) && ShiftAmount.ult(MaxMaskBitWidth) &&
+        Mask.isMask(ShiftAmount.getZExtValue())))
+    return SDValue();
+
+  APInt ExpectedMask =
+      APInt::getLowBitsSet(MaxMaskBitWidth, ShiftAmount.getZExtValue());
+  if (Mask != ExpectedMask)
----------------
RKSimon wrote:

not sure this is necessary - the Mask.isMask check should have caught it?

https://github.com/llvm/llvm-project/pull/220182


More information about the llvm-commits mailing list