This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Emit initial value saves in the proper place
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 15 Sep 2006 14:37:22 +0200
- Subject: Emit initial value saves in the proper place
The testcase testsuite/g++.old-deja/g++.other/singleton.C was failing in
our 4.1-based Blackfin compiler with -mfdpic.
This is the assembly we generated for the main function:
_main:
L$LFB$7:
LINK 20;
L$LCFI$3:
L$L$18:
[FP+-8] = P3;
P3 = [FP+-8];
L$LEHB$2:
call __ZN9singleton8instanceEv;
L$LEHE$2:
P3 = [FP+-8];
call __ZN9singleton5checkEv;
R0 += -2;
[FP+-4] = R0;
jump.s L$L$17;
L$L$22:
L$L$19:
P3 = [FP+-8];
call ___cxa_begin_catch;
P3 = [FP+-8];
L$LEHB$3:
call ___cxa_end_catch;
L$LEHE$3:
jump.s L$L$18;
L$L$17:
R0 = [FP+-4];
UNLINK;
rts;
We jump to L$LEHE$3 when catching an exception, and it jumps back to the
start of the loop. The problem is that calling a function and returning
through an exception may clobber P3. The code tries to save P3 to the
stack and reload it from there, but the save happens in the wrong place
- it's inside the loop. P3 is the PIC register, and having it clobbered
causes everything to go downhill rather quickly.
This is a bug in the initial_values pass, which tries to emit
instructions at the start of the function, but what it actually does is
emit them at the start of the first basic block. In this case, the
first basic block is part of a loop, so we may execute the save
instruction multiple times.
Fixed by emitting insns on the edge between the dummy entry block and
the first basic block instead. This is a regression from 3.4, which
emitted the insns right at the start of the function in all cases.
Bootstrapped on i686-linux, regression tested against bfin-elf.
Committed on mainline as 116968.
Bernd
Index: ChangeLog
===================================================================
--- ChangeLog (revision 116967)
+++ ChangeLog (working copy)
@@ -5,6 +5,10 @@
expanding the number of iterations.
* config/bfin/bfin.c (bfin_rtx_costs): Handle UDIV, UMOD.
+ * cfgrtl.c (emit_insn_at_entry): New function.
+ * rtl.h (emit_insn_at_entry): Declare it.
+ * integrate.c (emit_initial_value_sets): Use it.
+
2006-09-15 Kazu Hirata <kazu@codesourcery.com>
* doc/tm.texi (TARGET_FUNCTION_VALUE): Put @deftypefn all in
Index: cfgrtl.c
===================================================================
--- cfgrtl.c (revision 116965)
+++ cfgrtl.c (working copy)
@@ -453,6 +453,20 @@ entry_of_function (void)
BB_HEAD (ENTRY_BLOCK_PTR->next_bb) : get_insns ());
}
+/* Emit INSN at the entry point of the function, ensuring that it is only
+ executed once per function. */
+void
+emit_insn_at_entry (rtx insn)
+{
+ edge_iterator ei = ei_start (ENTRY_BLOCK_PTR->succs);
+ edge e = ei_safe_edge (ei);
+ if (!(e->flags & EDGE_FALLTHRU))
+ abort ();
+
+ insert_insn_on_edge (insn, e);
+ commit_edge_insertions ();
+}
+
/* Update insns block within BB. */
void
Index: integrate.c
===================================================================
--- integrate.c (revision 116965)
+++ integrate.c (working copy)
@@ -294,7 +294,7 @@ emit_initial_value_sets (void)
seq = get_insns ();
end_sequence ();
- emit_insn_after (seq, entry_of_function ());
+ emit_insn_at_entry (seq);
return 0;
}
Index: rtl.h
===================================================================
--- rtl.h (revision 116965)
+++ rtl.h (working copy)
@@ -2074,6 +2074,7 @@ extern rtx emit (rtx);
extern void renumber_insns (void);
extern rtx delete_insn (rtx);
extern rtx entry_of_function (void);
+extern void emit_insn_at_entry (rtx);
extern void delete_insn_chain (rtx, rtx);
extern rtx unlink_insn_chain (rtx, rtx);
extern rtx delete_insn_and_edges (rtx);