[llvm] [X86] Select i8 ANDN via i32 promotion (PR #205050)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 04:58:10 PDT 2026


================
@@ -51954,6 +51954,52 @@ static SDValue combineAndNotIntoANDNP(SDNode *N, const SDLoc &DL,
   return DAG.getNode(X86ISD::ANDNP, DL, VT, X, Y);
 }
 
+static SDValue combineI8AndNotIntoI32AndNot(SDNode *N, const SDLoc &DL,
+                                            SelectionDAG &DAG,
+                                            const X86Subtarget &Subtarget) {
+  assert(N->getOpcode() == ISD::AND && "Unexpected opcode combine into ANDN");
+
+  if (!Subtarget.hasBMI() || N->getValueType(0) != MVT::i8)
+    return SDValue();
+
+  // Keep compare and mask-lowering idioms in their existing byte forms.
+  for (SDUse &Use : N->uses()) {
+    if (Use.getResNo() != 0)
+      continue;
+    SDNode *User = Use.getUser();
+    if (User->getOpcode() == ISD::SETCC)
+      return SDValue();
+    if (User->getOpcode() == ISD::BITCAST) {
+      EVT UseVT = User->getValueType(0);
+      if (UseVT.isVector() && UseVT.getScalarType() == MVT::i1)
+        return SDValue();
+    }
+  }
+
+  SDValue X, Y;
+  SDValue N0 = N->getOperand(0);
+  SDValue N1 = N->getOperand(1);
+  if (SDValue Not = IsNOT(N0, DAG)) {
+    X = Not;
+    Y = N1;
+  } else if (SDValue Not = IsNOT(N1, DAG)) {
+    X = Not;
+    Y = N0;
+  } else
+    return SDValue();
+
+  if (X.getValueType() != MVT::i8 || Y.getValueType() != MVT::i8)
+    return SDValue();
----------------
mygitljf wrote:

`Y` cannot differ because it remains a direct operand of the i8 `ISD::AND`.`X` can differ because `IsNOT()` peeks through bitcasts and may expose the underlying value, for example `v8i1`. I'll remove the redundant `Y` check but retain the `X` check.

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


More information about the llvm-commits mailing list