[llvm] 8623da5 - [DAG] visitFREEZE - generalize freeze(op()) -> op(freeze()) to any number of operands

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 10 05:12:59 PDT 2022


Author: Simon Pilgrim
Date: 2022-08-10T13:12:46+01:00
New Revision: 8623da5f748bc36fc78fa148fd34332d386533ea

URL: https://github.com/llvm/llvm-project/commit/8623da5f748bc36fc78fa148fd34332d386533ea
DIFF: https://github.com/llvm/llvm-project/commit/8623da5f748bc36fc78fa148fd34332d386533ea.diff

LOG: [DAG] visitFREEZE - generalize freeze(op()) -> op(freeze()) to any number of operands

canCreateUndefOrPoison currently only handles unary ops, but we intend to change that soon - this more closely matches the pushFreezeToPreventPoisonFromPropagating behaviour where the freeze is pushed up to a single operand value, as long as all others are guaranteed not to be poison/undef.

However, pushFreezeToPreventPoisonFromPropagating would freeze all uses of the value - whilst this variant requires the frozen value to be only used in the op - we can look at generalize multiple uses later if the need arises.

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 7ba494033262..392b24af3716 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13868,13 +13868,40 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
   if (DAG.isGuaranteedNotToBeUndefOrPoison(N0, /*PoisonOnly*/ false))
     return N0;
 
-  // Fold freeze(unaryop(x)) -> unaryop(freeze(x)).
-  // TODO: Replace with pushFreezeToPreventPoisonFromPropagating fold and
-  // support getNumOperands() >= 1.
-  if (N0.getNumOperands() == 1 &&
-      !DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false) && N0->hasOneUse())
-    return DAG.getNode(N0.getOpcode(), SDLoc(N0), N->getValueType(0),
-                       DAG.getFreeze(N0.getOperand(0)));
+  // Fold freeze(op(x,y,z)) -> op(freeze(x),y,z).
+  // Try to push freeze through instructions that propagate but don't produce
+  // poison as far as possible. If an operand of freeze follows three
+  // conditions 1) one-use, 2) does not produce poison, and 3) has all but one
+  // guaranteed-non-poison operands then push the freeze through to the one
+  // operand that is not guaranteed non-poison.
+  if (!DAG.canCreateUndefOrPoison(N0, /*PoisonOnly*/ false) &&
+      N0->getNumValues() == 1 && N0->hasOneUse()) {
+    SDValue MaybePoisonOperand;
+    for (SDValue Op : N0->ops()) {
+      if (DAG.isGuaranteedNotToBeUndefOrPoison(Op, /*PoisonOnly*/ false))
+        continue;
+      if ((!MaybePoisonOperand && N0->isOnlyUserOf(Op.getNode())) ||
+          MaybePoisonOperand == Op) {
+        MaybePoisonOperand = Op;
+        continue;
+      }
+      // Multiple maybe-poison ops - bail out.
+      MaybePoisonOperand = SDValue();
+      break;
+    }
+    if (MaybePoisonOperand) {
+      // Recreate the node with the frozen maybe-poison operand.
+      // TODO: Drop the isOnlyUserOf constraint and replace all users of
+      // MaybePoisonOperand with FrozenMaybePoisonOperand
+      // to match pushFreezeToPreventPoisonFromPropagating behavior.
+      SDValue FrozenMaybePoisonOperand = DAG.getFreeze(MaybePoisonOperand);
+      SmallVector<SDValue> Ops(N0->op_begin(), N0->op_end());
+      for (SDValue &Op : Ops)
+        if (Op == MaybePoisonOperand)
+          Op = FrozenMaybePoisonOperand;
+      return DAG.getNode(N0.getOpcode(), SDLoc(N0), N0->getVTList(), Ops);
+    }
+  }
 
   return SDValue();
 }


        


More information about the llvm-commits mailing list