[llvm] [X86] Invert (and X, ~(and ~Y, Z)) back into (and X, (or Y, ~Z)) (PR #109215)

Miguel Saldivar via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 10 11:20:33 PDT 2024


================
@@ -50034,6 +50034,32 @@ static bool hasBZHI(const X86Subtarget &Subtarget, MVT VT) {
          (VT == MVT::i32 || (VT == MVT::i64 && Subtarget.is64Bit()));
 }
 
+/// InstCombine converts:
+///    `(and X, ~(and ~Y, Z))`
+/// to
+///    `(and X, (or Y, ~Z))`
+///
+/// But we should undo this transformation if the `andn` instruction is
+/// available to us.
+static SDValue combineAndNotOrIntoAndNotAnd(SDNode *N, SelectionDAG &DAG,
+                                            const X86Subtarget &Subtarget) {
+
+  using namespace llvm::SDPatternMatch;
+  MVT VT = N->getSimpleValueType(0);
+  SDLoc DL(N);
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+  if (TLI.hasAndNot(SDValue(N, 0))) {
----------------
Saldivarcher wrote:

So the latter is preferred?
```c++
static SDValue combineAndNotOrIntoAndNotAnd(SDNode *N, SelectionDAG &DAG) {

  using namespace llvm::SDPatternMatch;
  MVT VT = N->getSimpleValueType(0);
  SDLoc DL(N);
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  if (TLI.hasAndNot(SDValue(N, 0))) {
    SDValue X, Y, Z;
    if (sd_match(N, m_And(m_Value(X),
                          m_OneUse(m_Or(m_Value(Y), m_Not(m_Value(Z)))))))
      return DAG.getNode(
          ISD::AND, DL, VT, X,
          DAG.getNOT(
              DL, DAG.getNode(ISD::AND, DL, VT, DAG.getNOT(DL, Y, VT), Z), VT));
  }
  return SDValue();
}
```
vs
```cpp
static SDValue combineAndNotOrIntoAndNotAnd(SDNode *N, SelectionDAG &DAG) {

  using namespace llvm::SDPatternMatch;
  MVT VT = N->getSimpleValueType(0);
  SDLoc DL(N);
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  if (!TLI.hasAndNot(SDValue(N, 0)))
    return SDValue();

  SDValue X, Y, Z;
  if (sd_match(
          N, m_And(m_Value(X), m_OneUse(m_Or(m_Value(Y), m_Not(m_Value(Z)))))))
    return DAG.getNode(
        ISD::AND, DL, VT, X,
        DAG.getNOT(DL, DAG.getNode(ISD::AND, DL, VT, DAG.getNOT(DL, Y, VT), Z),
                   VT));

  return SDValue();
}
```

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


More information about the llvm-commits mailing list