This is the mail archive of the gcc-patches@gcc.gnu.org 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]

inline+sibcall x LEAF_REG_REMAP


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

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