[DAG] Move OR(AND(X,C1),AND(OR(X,Y),C2)) -> OR(AND(X,OR(C1,C2)),AND(Y,C2)) fold to...
authorSimon Pilgrim <llvm-dev@redking.me.uk>
Sat, 23 Jul 2022 12:11:07 +0000 (13:11 +0100)
committerSimon Pilgrim <llvm-dev@redking.me.uk>
Sat, 23 Jul 2022 12:17:24 +0000 (13:17 +0100)
This will fix the SystemZ v3i31 memcpy regression in D77804 (with the help of D129765 as well....).

It should also allow us to /bend/ the oneuse limitation for cases where we can use demanded bits to safely peek though multiple uses of the AND ops.

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

index ebc145b9b59c48834145b7527579311600001512..edb0756e8c3b51313ddae219d79960861ed8a75d 100644 (file)
@@ -6888,27 +6888,6 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1,
     if (getBitwiseNotOperand(N00, N01,
                              /* AllowUndefs */ false) == N1)
       return DAG.getNode(ISD::OR, SDLoc(N), VT, N01, N1);
-
-    // (or (and X, C1), (and (or X, Y), C2)) -> (or (and X, C1|C2), (and Y, C2))
-    if (N1.getOpcode() == ISD::AND) {
-      SDValue N10 = N1.getOperand(0);
-      if (N10.getOpcode() == ISD::OR) {
-        SDValue N11 = N1.getOperand(1);
-        SDValue N100 = N10.getOperand(0);
-        SDValue N101 = N10.getOperand(1);
-        if (((N00 == N100) || (N00 == N101)) && N0->hasOneUse() &&
-            N1->hasOneUse()) {
-          SDLoc DL(N);
-          if (SDValue C12 =
-                  DAG.FoldConstantArithmetic(ISD::OR, DL, VT, {N01, N11})) {
-            SDValue Y = (N00 == N100 ? N101 : N100);
-            return DAG.getNode(ISD::OR, DL, VT,
-                               DAG.getNode(ISD::AND, DL, VT, N00, C12),
-                               DAG.getNode(ISD::AND, DL, VT, Y, N11));
-          }
-        }
-      }
-    }
   }
 
   if (SDValue R = foldLogicOfShifts(N, N0, N1, DAG))
index 31ea506d306b1405e343b9e0d2e6e29fcbf08747..8f71b9f49ad47e58d353fd80b7f897f8243969e3 100644 (file)
@@ -1467,6 +1467,33 @@ bool TargetLowering::SimplifyDemandedBits(
       }
     }
 
+    // (or (and X, C1), (and (or X, Y), C2)) -> (or (and X, C1|C2), (and Y, C2))
+    // TODO: Use SimplifyMultipleUseDemandedBits to peek through masks.
+    if (Op0.getOpcode() == ISD::AND && Op1.getOpcode() == ISD::AND &&
+        Op0->hasOneUse() && Op1->hasOneUse()) {
+      // Attempt to match all commutations - m_c_Or would've been useful!
+      for (int I = 0; I != 2; ++I) {
+        SDValue X = Op.getOperand(I).getOperand(0);
+        SDValue C1 = Op.getOperand(I).getOperand(1);
+        SDValue Alt = Op.getOperand(1 - I).getOperand(0);
+        SDValue C2 = Op.getOperand(1 - I).getOperand(1);
+        if (Alt.getOpcode() == ISD::OR) {
+          for (int J = 0; J != 2; ++J) {
+            if (X == Alt.getOperand(J)) {
+              SDValue Y = Alt.getOperand(1 - J);
+              if (SDValue C12 = TLO.DAG.FoldConstantArithmetic(ISD::OR, dl, VT,
+                                                               {C1, C2})) {
+                SDValue MaskX = TLO.DAG.getNode(ISD::AND, dl, VT, X, C12);
+                SDValue MaskY = TLO.DAG.getNode(ISD::AND, dl, VT, Y, C2);
+                return TLO.CombineTo(
+                    Op, TLO.DAG.getNode(ISD::OR, dl, VT, MaskX, MaskY));
+              }
+            }
+          }
+        }
+      }
+    }
+
     Known |= Known2;
     break;
   }