This is the mail archive of the 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]

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:

         LINK 20;
         [FP+-8] = P3;
         P3 = [FP+-8];
         call __ZN9singleton8instanceEv;
         P3 = [FP+-8];
         call __ZN9singleton5checkEv;
         R0 += -2;
         [FP+-4] = R0;
         jump.s L$L$17;
         P3 = [FP+-8];
         call ___cxa_begin_catch;
         P3 = [FP+-8];
         call ___cxa_end_catch;
         jump.s L$L$18;
         R0 = [FP+-4];

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.


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  <>
 	* 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.  */
+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.  */
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);

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