This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PR42630] reset debug insns referencing unroll-expanded vars
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 08 Jan 2010 05:21:12 -0200
- Subject: [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