This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
inline+sibcall x LEAF_REG_REMAP
- To: gcc-patches at gcc dot gnu dot org
- Subject: inline+sibcall x LEAF_REG_REMAP
- From: Alexandre Oliva <aoliva at redhat dot com>
- Date: 10 Sep 2000 03:41:14 -0300
- Organization: GCC Team, Red Hat
I've been observing bootstrap -O3 failures on sparc for the past few
weeks. I've finally decided to try to track the bug down.
It turned out to be a bad interaction between an inlined sibcall and
leaf-register remapping. The testcase in the patch was derived from
ggc_mark_tree_hash_table{,_ptr}(), where the bug showed up.
bar() was compiled and, because of -O3, saved for inlining, before
CALL_PLACEHOLDER expansion. foo() ended up with a copy of the
CALL_PLACEHOLDER, because bar() was inlined at call_expand() time.
Later on, when rest_of_compilation() was run for the second time on
bar(), final would remap the leaf registers in-place, modifying the
calling-sequence patterns that were being shared with foo().
The solution I found was to prevent this sharing, copying remappable
registers at integration time, yet preserving sharing of that register
within the integrated insns. Ok to install, assuming bootstrap and
testing will succeed on sparc-sun-solaris2.7?
Index: gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* gcc.c-torture/execute/20000910-1.c: New test.
Index: gcc/testsuite/gcc.c-torture/execute/20000910-1.c
===================================================================
RCS file: 20000910-1.c
diff -N 20000910-1.c
--- /dev/null Tue May 5 13:32:27 1998
+++ gcc/testsuite/gcc.c-torture/execute/20000910-1.c Sat Sep 9 23:34:27 2000
@@ -0,0 +1,25 @@
+/* Copyright (C) 2000 Free Software Foundation */
+/* by Alexandre Oliva <aoliva@redhat.com> */
+
+void bar (int);
+void foo (int *);
+
+int main () {
+ static int a[] = { 0, 1, 2 };
+ int *i = &a[sizeof(a)/sizeof(*a)];
+
+ while (i-- > a)
+ foo (i);
+
+ exit (0);
+}
+
+void baz (int, int);
+
+void bar (int i) { baz (i, i); }
+void foo (int *i) { bar (*i); }
+
+void baz (int i, int j) {
+ if (i != j)
+ abort ();
+}
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* print-rtl.c (debug_call_placeholder_verbose): New variable.
(print_rtx) [CALL_PLACEHOLDER]: Dump all call sequences if it is
set.
* integrate.c (copy_rtx_and_substitute): Don't share
LEAF_REG_REMAPpable registers with the inlined function.
Index: gcc/print-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/print-rtl.c,v
retrieving revision 1.58
diff -u -p -r1.58 print-rtl.c
--- gcc/print-rtl.c 2000/08/04 20:28:05 1.58
+++ gcc/print-rtl.c 2000/09/10 06:34:28
@@ -63,6 +63,9 @@ int flag_dump_unnumbered = 0;
/* Nonzero if we are dumping graphical description. */
int dump_for_graph;
+/* Nonzero to dump all call_placeholder alternatives. */
+static int debug_call_placeholder_verbose;
+
/* Print IN_RTX onto OUTFILE. This is the recursive part of printing. */
static void
@@ -421,6 +424,37 @@ print_rtx (in_rtx)
break;
case CALL_PLACEHOLDER:
+ if (debug_call_placeholder_verbose)
+ {
+ fputs (" (cond [\n (const_string \"normal\") (sequence [", outfile);
+ for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
+ {
+ fputs ("\n ", outfile);
+ print_inline_rtx (outfile, tem, 4);
+ }
+
+ tem = XEXP (in_rtx, 1);
+ if (tem)
+ fputs ("\n ])\n (const_string \"tail_call\") (sequence [", outfile);
+ for (; tem != 0; tem = NEXT_INSN (tem))
+ {
+ fputs ("\n ", outfile);
+ print_inline_rtx (outfile, tem, 4);
+ }
+
+ tem = XEXP (in_rtx, 2);
+ if (tem)
+ fputs ("\n ])\n (const_string \"tail_recursion\") (sequence [", outfile);
+ for (; tem != 0; tem = NEXT_INSN (tem))
+ {
+ fputs ("\n ", outfile);
+ print_inline_rtx (outfile, tem, 4);
+ }
+
+ fputs ("\n ])\n ])", outfile);
+ break;
+ }
+
for (tem = XEXP (in_rtx, 0); tem != 0; tem = NEXT_INSN (tem))
if (GET_CODE (tem) == CALL_INSN)
{
Index: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/integrate.c,v
retrieving revision 1.113
diff -u -p -r1.113 integrate.c
--- gcc/integrate.c 2000/09/02 02:54:55 1.113
+++ gcc/integrate.c 2000/09/10 06:34:28
@@ -1758,7 +1758,7 @@ copy_rtx_and_substitute (orig, map, for_
equivalence for it to be the address. This will substitute the
address into insns where it can be substituted and use the new
pseudo where it can't. */
- if (regno == VIRTUAL_STACK_VARS_REGNUM)
+ else if (regno == VIRTUAL_STACK_VARS_REGNUM)
{
rtx loc, seq;
int size = get_func_frame_size (DECL_SAVED_INSNS (map->fndecl));
@@ -1845,7 +1845,26 @@ copy_rtx_and_substitute (orig, map, for_
else
return map->inline_target;
}
- return orig;
+#if defined (LEAF_REGISTERS) && defined (LEAF_REG_REMAP)
+ /* If leaf_renumber_regs_insn() might remap this register to
+ some other number, make sure we don't share it with the
+ inlined function, otherwise delayed optimization of the
+ inlined function may change it in place, breaking our
+ reference to it. We may still shared it within the
+ function, so create an entry for this register in the
+ reg_map. */
+ if (map->integrating
+ && LEAF_REGISTERS[regno] && LEAF_REG_REMAP(regno) != regno)
+ {
+ temp = gen_rtx_REG (mode, regno);
+ map->reg_map[regno] = temp;
+ return temp;
+ }
+#endif
+ else
+ return orig;
+
+ abort ();
}
if (map->reg_map[regno] == NULL)
{
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me