This patch fixes PR64331 which produced wrong code because of outdated (too
many) REG_DEAD notes. These notes are not (re)computed per default, hence do
the computation by hand each time avr.c:reg_unused_after is called in a
different pass.
Ok to apply?
Johann
gcc/
PR target/64331
* config/avr/avr.c (reg_unused_after): Recompute insn notes if the
pass changed since the last (re)computation.
* config/avr/avr.h (machine_function.dead_notes_pass_number): New
component.
gcc/testsuite/
PR target/64331
* gcc.target/avr/torture/pr64331.c: New run test.
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c (revision 220738)
+++ config/avr/avr.c (working copy)
@@ -51,6 +51,7 @@
#include "target-def.h"
#include "params.h"
#include "df.h"
+#include "tree-pass.h" /* for current_pass */
/* Maximal allowed offset for an address in the LD command */
#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
@@ -7862,8 +7863,22 @@ avr_adjust_insn_length (rtx insn, int le
int
reg_unused_after (rtx insn, rtx reg)
{
+ if (cfun->machine->dead_notes_pass_number
+ != current_pass->static_pass_number)
+ {
+ /* `dead_or_set_p' needs correct REG_DEAD notes, cf. PR64331. Hence
+ recompute them each time we find ourselves in a different pass.
+ `reg_unused_after' is used during final for insn output, and in
+ some earlier passes it is involved in insn length computations. */
+
+ df_note_add_problem ();
+ df_analyze ();
+
+ cfun->machine->dead_notes_pass_number = current_pass->static_pass_number;
+ }
+
return (dead_or_set_p (insn, reg)
- || (REG_P(reg) && _reg_unused_after (insn, reg)));
+ || (REG_P (reg) && _reg_unused_after (insn, reg)));
}
/* Return nonzero if REG is not used after INSN.
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h (revision 220738)
+++ config/avr/avr.h (working copy)
@@ -592,6 +592,10 @@ struct GTY(()) machine_function
/* 'true' if the above is_foo predicates are sanity-checked to avoid
multiple diagnose for the same function. */
int attributes_checked_p;
+
+ /* The latest static pass number for which REG_DEAD notes have been
+ computed, cf. PR64331. */
+ int dead_notes_pass_number;
};
/* AVR does not round pushes, but the existence of this macro is
Index: testsuite/gcc.target/avr/torture/pr64331.c
===================================================================
--- testsuite/gcc.target/avr/torture/pr64331.c (revision 0)
+++ testsuite/gcc.target/avr/torture/pr64331.c (revision 0)
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+
+typedef struct
+{
+ unsigned a, b;
+} T2;
+
+
+__attribute__((__noinline__, __noclone__))
+void foo2 (T2 *t, int x)
+{
+ if (x != t->a)
+ {
+ t->a = x;
+
+ if (x && x == t->b)
+ t->a = 20;
+ }
+}
+
+
+T2 t;
+
+int main (void)
+{
+ t.a = 1;
+ t.b = 1234;
+
+ foo2 (&t, 1234);
+
+ if (t.a != 20)
+ __builtin_abort();
+
+ __builtin_exit (0);
+
+ return 0;
+}
+