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]

[PR42630] reset debug insns referencing unroll-expanded vars


-fvariable-expansion-in-unroller wants to turn:

<loop>
...
  R = R + 1
...
<endloop>

into

  R' = 0
<loop>
...
  R = R + 1
...
<unrolled>
...
  R' = R' + 1
...
<endloop>
  R = R + R'

It requires R to be referenced in a single insn.  This means a debug
insn would disable the optimization.  That was easy to fix.

Not so easy was figuring out how to adjust the debug insns.  Consider:

<loop>
...
  R = R + 1
  # debug var => R
...
<endloop>
  # debug var => R

We could correctly expand this to:

  R' = 0
<loop>
...
  R = R + 1
  # debug var => R + R'
...
<unrolled>
...
  R' = R' + 1
  # debug var => R + R'
...
<endloop>
  R = R + R'
  # debug var => R

However, taking note of which debug insns will require updating because
of each expanded var, and performing the updates at the end, turned out
to require working too hard.  I decided to just reset the debug insns
instead, which at least fixes the incorrect debug info we'd get if we
left them alone referencing the original R.

Ok to install if it passes regstrapping?

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/42630
	* loop-unroll.c (referenced_in_one_insn_in_loop_p): Count debug
	uses in new incoming argument.
	(reset_debug_uses_in_loop): New.
	(analyze_insn_to_expand_var): Call the latter if the former found
	anything.  Fix whitespace.  Reject invalid dest overlaps before
	going through all insns in the loop.

for  gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/42630
	* gcc.dg/pr42630.c: New.

Index: gcc/loop-unroll.c
===================================================================
--- gcc/loop-unroll.c.orig	2010-01-08 03:42:07.000000000 -0200
+++ gcc/loop-unroll.c	2010-01-08 05:08:33.000000000 -0200
@@ -1,5 +1,5 @@
 /* Loop unrolling and peeling.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -142,7 +142,7 @@ static void opt_info_start_duplication (
 static void apply_opt_in_copies (struct opt_info *, unsigned, bool, bool);
 static void free_opt_info (struct opt_info *);
 static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx);
-static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx);
+static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx, int *);
 static struct iv_to_split *analyze_iv_to_split_insn (rtx);
 static void expand_var_during_unrolling (struct var_to_expand *, rtx);
 static void insert_var_expansion_initialization (struct var_to_expand *,
@@ -1525,10 +1525,13 @@ ve_info_eq (const void *ivts1, const voi
   return i1->insn == i2->insn;
 }
 
-/* Returns true if REG is referenced in one insn in LOOP.  */
+/* Returns true if REG is referenced in one nondebug insn in LOOP.
+   Set *DEBUG_USES to the number of debug insns that reference the
+   variable.  */
 
 bool
-referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg)
+referenced_in_one_insn_in_loop_p (struct loop *loop, rtx reg,
+				  int *debug_uses)
 {
   basic_block *body, bb;
   unsigned i;
@@ -1541,14 +1544,43 @@ referenced_in_one_insn_in_loop_p (struct
       bb = body[i];
 
       FOR_BB_INSNS (bb, insn)
-      {
-        if (rtx_referenced_p (reg, insn))
-          count_ref++;
-      }
+	if (!rtx_referenced_p (reg, insn))
+	  continue;
+	else if (DEBUG_INSN_P (insn))
+	  ++*debug_uses;
+	else if (++count_ref > 1)
+	  break;
     }
   return (count_ref  == 1);
 }
 
+/* Reset the DEBUG_USES debug insns in LOOP that reference REG.  */
+
+static void
+reset_debug_uses_in_loop (struct loop *loop, rtx reg, int debug_uses)
+{
+  basic_block *body, bb;
+  unsigned i;
+  rtx insn;
+
+  body = get_loop_body (loop);
+  for (i = 0; debug_uses && i < loop->num_nodes; i++)
+    {
+      bb = body[i];
+
+      FOR_BB_INSNS (bb, insn)
+	if (!DEBUG_INSN_P (insn) || !rtx_referenced_p (reg, insn))
+	  continue;
+	else
+	  {
+	    validate_change (insn, &INSN_VAR_LOCATION_LOC (insn),
+			     gen_rtx_UNKNOWN_VAR_LOC (), 0);
+	    if (!--debug_uses)
+	      break;
+	  }
+    }
+}
+
 /* Determine whether INSN contains an accumulator
    which can be expanded into separate copies,
    one for each copy of the LOOP body.
@@ -1579,6 +1611,7 @@ analyze_insn_to_expand_var (struct loop 
   struct var_to_expand *ves;
   enum machine_mode mode1, mode2;
   unsigned accum_pos;
+  int debug_uses = 0;
 
   set = single_set (insn);
   if (!set)
@@ -1624,15 +1657,15 @@ analyze_insn_to_expand_var (struct loop 
      the expansions at the end of the computation will yield wrong results
      for (x = something - x) thus avoid using it in that case.  */
   if (accum_pos == 1
-    && GET_CODE (src) == MINUS)
+      && GET_CODE (src) == MINUS)
    return NULL;
 
-  something = (accum_pos == 0)? op2 : op1;
+  something = (accum_pos == 0) ? op2 : op1;
 
-  if (!referenced_in_one_insn_in_loop_p (loop, dest))
+  if (rtx_referenced_p (dest, something))
     return NULL;
 
-  if (rtx_referenced_p (dest, something))
+  if (!referenced_in_one_insn_in_loop_p (loop, dest, &debug_uses))
     return NULL;
 
   mode1 = GET_MODE (dest);
@@ -1650,6 +1683,17 @@ analyze_insn_to_expand_var (struct loop 
     fprintf (dump_file, "\n");
   }
 
+  if (debug_uses)
+    /* Instead of resetting the debug insns, we could replace each
+       debug use in the loop with the sum or product of all expanded
+       accummulators.  Since we'll only know of all expansions at the
+       end, we'd have to keep track of which vars_to_expand a debug
+       insn in the loop references, take note of each copy of the
+       debug insn during unrolling, and when it's all done, compute
+       the sum or product of each variable and adjust the original
+       debug insn and each copy thereof.  What a pain!  */
+    reset_debug_uses_in_loop (loop, dest, debug_uses);
+
   /* Record the accumulator to expand.  */
   ves = XNEW (struct var_to_expand);
   ves->insn = insn;
Index: gcc/testsuite/gcc.dg/pr42630.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/pr42630.c	2010-01-08 05:03:52.000000000 -0200
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fvariable-expansion-in-unroller -funroll-loops -fcompare-debug" } */
+
+int sum(int *buf, int len)
+{
+  int s = 0;
+  while (--len > 0) s += *buf++;
+  return s;
+}
-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

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