This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [4.5] Better support for widening multiplies


I put together this code...  the main difference with yours is that it
only propagates if the use has a single definition.  This is needed for
the DF update, and in 4.5 I want to use this to stop using (explicitly)
use-def chains.  UD chains are expensive and turning them off will allow
enabling of fwprop at -O1.

On one hand it might not catch some cases that your catch did, on the
other hand doing this in forward_propagate_into might enable more cascading.

I don't ask you to look at it right now, just if you post some testcases
(any target will do) I'll check if my code optimizes them.

Steven, what do you think?

Paolo
--- fwprop.c.old	2009-02-17 17:41:58.000000000 +0100
+++ fwprop.c	2009-02-17 18:20:22.000000000 +0100
@@ -1047,6 +1048,120 @@
   return def;
 }
 
+/* Determine whether DEF is an extension of a subreg from NARROW_MODE
+   has the same value as the full reg.  If so, return ZERO_EXTEND
+   or SIGN_EXTEND as appropriate; UNKNOWN if we are not successful.  */
+
+static enum rtx_code
+find_extend_code (df_ref def, enum machine_mode narrow_mode)
+{
+  rtx def_set, src;
+  enum rtx_code src_code;
+
+  def_set = single_set (DF_REF_INSN (def));
+  src = SET_SRC (def_set);
+  src_code = GET_CODE (src);
+
+  if ((src_code == SIGN_EXTEND || src_code == ZERO_EXTEND)
+      && GET_MODE (XEXP (src, 0)) == narrow_mode)
+    return src_code;
+  if (src_code == ASHIFTRT
+      && GET_CODE (XEXP (src, 1)) == CONST_INT
+      && INTVAL (XEXP (src, 1)) == GET_MODE_BITSIZE (narrow_mode))
+    return SIGN_EXTEND;
+  else if (src_code == LSHIFTRT
+	   && GET_CODE (XEXP (src, 1)) == CONST_INT
+	   && INTVAL (XEXP (src, 1)) == GET_MODE_BITSIZE (narrow_mode))
+    return ZERO_EXTEND;
+  else
+    return UNKNOWN;
+}
+
+
+/* Look at the insn including USE and if it is a multiplication try to
+  propagate from *both* operands into it, synthesizing a widening
+  multiplication.  */
+
+static bool
+forward_propagate_into_multiply (df_ref use)
+{
+  rtx insn, set, src;
+  rtx op0, op1, t;
+  df_ref def0, def1, use0, use1, u;
+  enum rtx_code op0_code, op1_code;
+  enum machine_mode mode, narrow_mode;
+  enum fwprop_result result;
+
+  if (DF_REF_FLAGS (use) & (DF_REF_READ_WRITE | DF_REF_IN_NOTE))
+    return false;
+  if (DF_REF_IS_ARTIFICIAL (use))
+    return false;
+
+  insn = DF_REF_INSN (use);
+  set = single_set (insn);
+  if (set == NULL_RTX)
+    return false;
+
+  src = SET_SRC (set);
+  if (GET_CODE (src) != MULT)
+    return false;
+
+  mode = GET_MODE (SET_DEST (set));
+  if (GET_MODE_SIZE (mode) <= 1
+      || exact_log2 (GET_MODE_SIZE (mode)) < 0
+      || GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  op0 = XEXP (src, 0);
+  op1 = XEXP (src, 1);
+  if (!REG_P (op0) || HARD_REGISTER_P (op0)
+      || !REG_P (op1) || HARD_REGISTER_P (op1))
+    return false;
+
+  use0 = df_find_use (insn, op0);
+  def0 = find_fwprop_def (def0);
+  narrow_mode = mode_for_size (GET_MODE_BITSIZE (mode) / 2, MODE_INT, 1);
+  if ((op0_code = find_extend_code (def0, narrow_mode)) == UNKNOWN)
+    return false;
+
+  use1 = df_find_use (insn, op1);
+  def1 = find_fwprop_def (def1);
+  if ((op1_code = find_extend_code (def1, narrow_mode)) == UNKNOWN)
+    return false;
+
+  /* For mixed signed * unsigned multiplications, the canonical form has
+     the unsigned operand first.  */
+  if (op0_code == SIGN_EXTEND && op1_code == ZERO_EXTEND)
+    {
+      t = op0, op0 = op1, op1 = t;
+      u = def0, def0 = def1, def1 = u;
+      u = use0, use0 = use1, use1 = u;
+      op0_code = ZERO_EXTEND;
+      op1_code = SIGN_EXTEND;
+    }
+
+  op0 = gen_lowpart (narrow_mode, op0);
+  op1 = gen_lowpart (narrow_mode, op1);
+  validate_change (insn, &XEXP (src, 0),
+		   gen_rtx_fmt_e (op0_code, mode, op0), 1);
+  validate_change (insn, &XEXP (src, 1),
+		   gen_rtx_fmt_e (op1_code, mode, op1), 1);
+
+  result = finish_fwprop (insn, -1, true);
+  if (result == FWP_FAILURE)
+    return false;
+
+  update_df (use0, &XEXP (src, 0), DF_REF_INSN (def0), result);
+  update_df (use1, &XEXP (src, 1), DF_REF_INSN (def1), result);
+  if (result != FWP_NOTE)
+    {
+      df_ref_remove (use0); 
+      df_ref_remove (use1); 
+    }
+  return true;
+}
+
+
 
 /* Given a use USE of an insn, if it has a single reaching
    definition, try to forward propagate it into that insn.  */
@@ -1057,6 +1172,9 @@
   df_ref def;
   rtx def_insn, def_set;
 
+  if (forward_propagate_into_multiply (use))
+    return;
+
   def = find_fwprop_def (use);
   if (!def)
     return;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]