Attached is what I have for carry_backpropagate .

The utility of special handling for SS_ASHIFT / US_ASHIFT seems
somewhat marginal.

I suspect it'd be more useful to add handling of LSHIFTRT and ASHIFTRT
.  Some ports do
a lot of static shifting.
commit ed47c3d0d38f85c9b4e22bdbd079e0665465ef9c
Author: Joern Rennecke <joern.renne...@embecosm.com>
Date:   Wed Nov 29 18:46:06 2023 +0000

    * ext-dce.c: Fixes for carry handling.
    
    * ext-dce.c (safe_for_live_propagation): Handle MINUS.
      (ext_dce_process_uses): Break out carry handling into ..
      (carry_backpropagate): This new function.
      Better handling of ASHIFT.
      Add handling of SMUL_HIGHPART, UMUL_HIGHPART, SIGN_EXTEND, SS_ASHIFT and
      US_ASHIFT.

diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index 590656f72c7..2a4508181a1 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -83,6 +83,7 @@ safe_for_live_propagation (rtx_code code)
     case SIGN_EXTEND:
     case TRUNCATE:
     case PLUS:
+    case MINUS:
     case MULT:
     case SMUL_HIGHPART:
     case UMUL_HIGHPART:
@@ -365,6 +366,67 @@ binop_implies_op2_fully_live (rtx_code code)
     }
 }
 
+/* X, with code CODE, is an operation for which
+safe_for_live_propagation holds true,
+   and bits set in MASK are live in the result.  Compute a make of 
(potentially)
+   live bits in the non-constant inputs.  In case of
+binop_implies_op2_fully_live
+   (e.g. shifts), the computed mask may exclusively pertain to the
+first operand.  */
+
+HOST_WIDE_INT
+carry_backpropagate (HOST_WIDE_INT mask, enum rtx_code code, rtx x)
+{
+  enum machine_mode mode = GET_MODE (x);
+  HOST_WIDE_INT mmask = GET_MODE_MASK (mode);
+  switch (code)
+    {
+    case ASHIFT:
+      if (CONSTANT_P (XEXP (x, 1))
+         && known_lt (UINTVAL (XEXP (x, 1)), GET_MODE_BITSIZE (mode)))
+       return mask >> INTVAL (XEXP (x, 1));
+      /* Fall through.  */
+    case PLUS: case MINUS:
+    case MULT:
+      return mask ? ((2ULL << floor_log2 (mask)) - 1) : 0;
+    case SMUL_HIGHPART: case UMUL_HIGHPART:
+      if (!mask || XEXP (x, 1) == const0_rtx)
+       return 0;
+      if (CONSTANT_P (XEXP (x, 1)))
+       {
+         if (pow2p_hwi (INTVAL (XEXP (x, 1))))
+           return mmask & (mask << (GET_MODE_BITSIZE (mode).to_constant ()
+                                    - exact_log2 (INTVAL (XEXP (x, 1)))));
+
+         int bits = (2 * GET_MODE_BITSIZE (mode).to_constant ()
+                     - clz_hwi (mask) - ctz_hwi (INTVAL (XEXP (x, 1))));
+         if (bits < GET_MODE_BITSIZE (mode).to_constant ())
+           return (1ULL << bits) - 1;
+       }
+      return mmask;
+    case SIGN_EXTEND:
+      if (mask & ~mmask)
+       mask |= 1ULL << (GET_MODE_BITSIZE (mode).to_constant () - 1);
+      return mask;
+
+    /* We propagate for the shifted operand, but not the shift
+       count.  The count is handled specially.  */
+    case SS_ASHIFT:
+    case US_ASHIFT:
+      if (!mask || XEXP (x, 1) == const0_rtx)
+       return 0;
+      if (CONSTANT_P (XEXP (x, 1))
+         && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (mode).to_constant ())
+       {
+         return ((mmask & ~((unsigned HOST_WIDE_INT)mmask
+                            >> (INTVAL (XEXP (x, 1)) + (code == SS_ASHIFT))))
+                 | (mask >> INTVAL (XEXP (x, 1))));
+       }
+      return mmask;
+    default:
+      return mask;
+    }
+}
 /* Process uses in INSN contained in OBJ.  Set appropriate bits in LIVENOW
    for any chunks of pseudos that become live, potentially filtering using
    bits from LIVE_TMP.
@@ -480,11 +542,7 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj, bitmap 
livenow,
                 sure everything that should get marked as live is marked
                 from here onward.  */
 
-             /* ?!? What is the point of this adjustment to DST_MASK?  */
-             if (code == PLUS || code == MINUS
-                 || code == MULT || code == ASHIFT)
-               dst_mask
-                 = dst_mask ? ((2ULL << floor_log2 (dst_mask)) - 1) : 0;
+             dst_mask = carry_backpropagate (dst_mask, code, src);
 
              /* We will handle the other operand of a binary operator
                 at the bottom of the loop by resetting Y.  */

Reply via email to