[PATCH] Use comdat for sparc PIC thunks...

David Miller davem@davemloft.net
Thu Mar 11 22:11:00 GMT 2010


This makes sparc emit PIC thunks just like i386 does, by putting them
into a comdat section and therefore the linker only emits one copy in
the final image.

In a glibc build alone there are more than 800 stubs emitted in the
libc shared library.  With alignment and whatnot this conservatively
wastes more than 24k of object space, as well as cause horrible
I-cache behavior.  libgcc.so wastage cause by this is about 2K.

I've coded this up so that it's easy to emit stubs for other registers
at some point.  Hopefully we can use that to, for example, still use
leaf functions even if a PIC reference is made.

Maybe there is a way we can do this using Solaris's linker and
assembler's facilities too?

In any event if a Solaris person can test this I would really
appreciate it.

Thanks!

gcc/

2010-03-11  David S. Miller  <davem@davemloft.net>

	* config/sparc/sparc.c (emit_pic_helper): Delete.
	(pic_helper_symbol_name): Delete.
	(pic_helper_emitted_p): Delete.
	(pic_helper_needed): New.
	(USE_HIDDEN_LINKONCE): Define to '1' if HAVE_GAS_HIDDEN else '0'.
	(get_pc_thunk_name): New.
	(load_pic_register): Remove 'delay_pic_helper' arg.  Use
	get_thunk_pc_name and ggc_strdup to generate PIC thunk symbol.
	Set pic_helper_needed to true.  Don't call emit_pic_helper.
	(sparc_expand_prologue): Update load_pic_register call.
	(sparc_output_mi_thunk): Likewise.
	(sparc_file_end): Emit a hidden comdat symbol for the PIC
	thunk if possible.

diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e4ef862..067789b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -362,8 +362,7 @@ static rtx sparc_builtin_saveregs (void);
 static int epilogue_renumber (rtx *, int);
 static bool sparc_assemble_integer (rtx, unsigned int, int);
 static int set_extends (rtx);
-static void emit_pic_helper (void);
-static void load_pic_register (bool);
+static void load_pic_register (void);
 static int save_or_restore_regs (int, int, rtx, int, int);
 static void emit_save_or_restore_regs (int);
 static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
@@ -2908,9 +2907,8 @@ sparc_cannot_force_const_mem (rtx x)
 }
 
 /* PIC support.  */
-static GTY(()) char pic_helper_symbol_name[256];
+static GTY(()) bool pic_helper_needed = false;
 static GTY(()) rtx pic_helper_symbol;
-static GTY(()) bool pic_helper_emitted_p = false;
 static GTY(()) rtx global_offset_table;
 
 /* Ensure that we are not using patterns that are not OK with PIC.  */
@@ -3521,34 +3519,31 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
   return x;
 }
 
-/* Emit the special PIC helper function.  */
+#ifdef HAVE_GAS_HIDDEN
+# define USE_HIDDEN_LINKONCE 1
+#else
+# define USE_HIDDEN_LINKONCE 0
+#endif
 
 static void
-emit_pic_helper (void)
+get_pc_thunk_name (char name[32], unsigned int regno)
 {
-  const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
-  int align;
+  const char *pic_name = reg_names[regno];
 
-  switch_to_section (text_section);
+  /* Skip the leading '%' as that cannot be used in a
+     symbol name.  */
+  pic_name += 1;
 
-  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-  if (align > 0)
-    ASM_OUTPUT_ALIGN (asm_out_file, align);
-  ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name);
-  if (flag_delayed_branch)
-    fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
-	    pic_name, pic_name);
+  if (USE_HIDDEN_LINKONCE)
+    sprintf (name, "__sparc.get_pc_thunk.%s", pic_name);
   else
-    fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
-	    pic_name, pic_name);
-
-  pic_helper_emitted_p = true;
+    ASM_GENERATE_INTERNAL_LABEL (name, "LADDPC", regno);
 }
 
 /* Emit code to load the PIC register.  */
 
 static void
-load_pic_register (bool delay_pic_helper)
+load_pic_register (void)
 {
   int orig_flag_pic = flag_pic;
 
@@ -3560,18 +3555,18 @@ load_pic_register (bool delay_pic_helper)
     }
 
   /* If we haven't initialized the special PIC symbols, do so now.  */
-  if (!pic_helper_symbol_name[0])
+  if (!pic_helper_needed)
     {
-      ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0);
-      pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name);
+      char name[32];
+
+      pic_helper_needed = true;
+
+      get_pc_thunk_name (name, REGNO (pic_offset_table_rtx));
+      pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+
       global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
     }
 
-  /* If we haven't emitted the special PIC helper function, do so now unless
-     we are requested to delay it.  */
-  if (!delay_pic_helper && !pic_helper_emitted_p)
-    emit_pic_helper ();
-
   flag_pic = 0;
   if (TARGET_ARCH64)
     emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table,
@@ -4221,7 +4216,7 @@ sparc_expand_prologue (void)
 
   /* Load the PIC register if needed.  */
   if (flag_pic && crtl->uses_pic_offset_table)
-    load_pic_register (false);
+    load_pic_register ();
 }
 
 /* This function generates the assembly code for function entry, which boils
@@ -8882,7 +8877,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
 	  start_sequence ();
 	  /* Delay emitting the PIC helper function because it needs to
 	     change the section and we are emitting assembly code.  */
-	  load_pic_register (true);  /* clobbers %o7 */
+	  load_pic_register ();  /* clobbers %o7 */
 	  scratch = legitimize_pic_address (funexp, scratch);
 	  seq = get_insns ();
 	  end_sequence ();
@@ -9038,8 +9033,46 @@ static void
 sparc_file_end (void)
 {
   /* If we haven't emitted the special PIC helper function, do so now.  */
-  if (pic_helper_symbol_name[0] && !pic_helper_emitted_p)
-    emit_pic_helper ();
+  if (pic_helper_needed)
+    {
+      unsigned int regno = REGNO (pic_offset_table_rtx);
+      const char *pic_name = reg_names[regno];
+      char name[32];
+
+      get_pc_thunk_name (name, regno);
+      if (USE_HIDDEN_LINKONCE)
+	{
+	  tree decl;
+
+	  decl = build_decl (BUILTINS_LOCATION,
+			     FUNCTION_DECL, get_identifier (name),
+			     error_mark_node);
+	  TREE_PUBLIC (decl) = 1;
+	  TREE_STATIC (decl) = 1;
+	  DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+
+	  (*targetm.asm_out.unique_section) (decl, 0);
+	  switch_to_section (get_named_section (decl, NULL, 0));
+
+	  (*targetm.asm_out.globalize_label) (asm_out_file, name);
+	  fputs ("\t.hidden\t", asm_out_file);
+	  assemble_name (asm_out_file, name);
+	  putc ('\n', asm_out_file);
+	  ASM_OUTPUT_TYPE_DIRECTIVE (asm_out_file, name, "function");
+	}
+      else
+	{
+	  switch_to_section (text_section);
+	}
+      ASM_OUTPUT_LABEL (asm_out_file, name);
+
+      if (flag_delayed_branch)
+	fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
+		 pic_name, pic_name);
+      else
+	fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
+		 pic_name, pic_name);
+    }
 
   if (NEED_INDICATE_EXEC_STACK)
     file_end_indicate_exec_stack ();



More information about the Gcc-patches mailing list