This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

[commit] SPU i-cache: Correct calculation of number of required stubs (2/2)


Hello,

after the previous patch, I was still seeing off-by-one errors in the number
of required call stubs.    It turned out that this was caused by remove_cycles
eliminating some of the call_info edges.  While it is true that you need to
remove those edges when recursively traversing the call graph, you actually
need to consider all of the edges when counting stubs.

The following patch changes remove_cycles to not actually eliminate the edges,
but instead simply mark them with an broken_cycle flag.  This allows some users
to ignore them and others to take them into account ...

Note that this problem was latent not only with software i-cache, but also
with traditional automatic overlay generation.

Tested on spu-elf with no regressions.
Approved off-line by Alan Modra; committed to mainline.

Bye,
Ulrich


ChangeLog:

	* elf32-spu.c (struct call_info): New member broken_cycle.
	(remove_cycle): Instead of physically removing call_info structures
	to break call graph cycles, mark them using the broken_cycle flag.
	(mark_overlay_section): Respect broken_cycle flag.
	(unmark_overlay_section): Likewise.
	(collect_lib_sections): Likewise.
	(collect_overlays): Likewise.
	(sum_stack): Likewise.

--- src/bfd/elf32-spu.c.orig	2009-05-26 21:26:39.000000000 +0200
+++ src/bfd/elf32-spu.c	2009-05-26 21:24:41.000000000 +0200
@@ -367,6 +367,7 @@ struct call_info
   unsigned int max_depth;
   unsigned int is_tail : 1;
   unsigned int is_pasted : 1;
+  unsigned int broken_cycle : 1;
   unsigned int priority : 13;
 };
 
@@ -3267,9 +3268,8 @@ remove_cycles (struct function_info *fun
 				       "from %s to %s\n"),
 				     f1, f2);
 	    }
-	  *callp = call->next;
-	  free (call);
-	  continue;
+
+	  call->broken_cycle = TRUE;
 	}
       callp = &call->next;
     }
@@ -3512,7 +3512,8 @@ mark_overlay_section (struct function_in
 	  BFD_ASSERT (!fun->sec->segment_mark);
 	  fun->sec->segment_mark = 1;
 	}
-      if (!mark_overlay_section (call->fun, info, param))
+      if (!call->broken_cycle
+	  && !mark_overlay_section (call->fun, info, param))
 	return FALSE;
     }
 
@@ -3572,7 +3573,8 @@ unmark_overlay_section (struct function_
     }
 
   for (call = fun->call_list; call != NULL; call = call->next)
-    if (!unmark_overlay_section (call->fun, info, param))
+    if (!call->broken_cycle
+	&& !unmark_overlay_section (call->fun, info, param))
       return FALSE;
 
   if (RECURSE_UNMARK)
@@ -3623,7 +3625,8 @@ collect_lib_sections (struct function_in
     }
 
   for (call = fun->call_list; call != NULL; call = call->next)
-    collect_lib_sections (call->fun, info, param);
+    if (!call->broken_cycle)
+      collect_lib_sections (call->fun, info, param);
 
   return TRUE;
 }
@@ -3817,7 +3820,7 @@ collect_overlays (struct function_info *
 
   fun->visit7 = TRUE;
   for (call = fun->call_list; call != NULL; call = call->next)
-    if (!call->is_pasted)
+    if (!call->is_pasted && !call->broken_cycle)
       {
 	if (!collect_overlays (call->fun, info, ovly_sections))
 	  return FALSE;
@@ -3863,7 +3866,8 @@ collect_overlays (struct function_info *
     }
 
   for (call = fun->call_list; call != NULL; call = call->next)
-    if (!collect_overlays (call->fun, info, ovly_sections))
+    if (!call->broken_cycle
+	&& !collect_overlays (call->fun, info, ovly_sections))
       return FALSE;
 
   if (added_fun)
@@ -3914,6 +3918,8 @@ sum_stack (struct function_info *fun,
   max = NULL;
   for (call = fun->call_list; call; call = call->next)
     {
+      if (call->broken_cycle)
+	continue;
       if (!call->is_pasted)
 	has_call = TRUE;
       if (!sum_stack (call->fun, info, sum_stack_param))
@@ -3957,7 +3963,7 @@ sum_stack (struct function_info *fun,
 	{
 	  info->callbacks->minfo (_("  calls:\n"));
 	  for (call = fun->call_list; call; call = call->next)
-	    if (!call->is_pasted)
+	    if (!call->is_pasted && !call->broken_cycle)
 	      {
 		const char *f2 = func_name (call->fun);
 		const char *ann1 = call->fun == max ? "*" : " ";
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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