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]
Other format: [Raw text]

Re: Group static constructors and destructors in specific subsections, take 2


Hi,
this is updated patch.  I addressed, I hope, all the comments except for
removing USE_SELECT_SECTION_FOR_FUNCTIONS. I am somewhat confused by darwin and
thus would like to handle it incrementally.

I've removed the subsection hash, the string concatenations and section hash
should be fast enough given that we switch twice per function at most.  I also
added flag to tree_decl_with_vis specifying whether section name is implied by
-ffunction-sections or given by user and made default_function_section to do
text.unlikely.function_name by default.  I kept adding the _unlikely only for
darwin.  It was developed there and I suppose the funny suffixes do have
meaning for darwin linker.

Bootstrapped/regtested x86_64-linux, OK (after testing darwin and ia64)?

Honza

	* tree.h (DECL_HAS_IMPLICIT_SECTION_NAME_P): New macro.
	(tree_decl_with_vis): Add implicit_section_name_p.
	* targhooks.h (default_function_section): Declare.
	* target.def (function_section): New hook.
	* defaults.h (HOT_TEXT_SECTION_NAME,
	UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Remove.
	* predict.c (choose_function_section): Remove.
	(estimate_bb_frequencies): Do not use choose_function_section.
	* coretypes.h (enum node_frequency): Move here from cgraph.h
	* cgraph.h (enum node_frequency): Remove.
	* varasm.c (initialize_cold_section_name, unlikely_text_section,
	unlikely_text_section_p): Remove.
	(named_subsection_entry): New structure.
	(get_text_section): New function.
	(default_function_section): New function.
	(function_section_1): Break out from ...; handle profile info.
	(function_section): ... here.
	(unlikely_text_section): Remove.
	(unlikely_text_section_p): Use function_section_1.
	(assemble_start_function): Do not initialize cold section.
	(default_section_type_flags): Do not special case cold subsection.
	(switch_to_section): Likewise.
	* output.h (get_text_section): Define.
	* config/i386/winnt.c: Do not special case cold section.
	* config/darwin-protos.h (darwin_function_section): Declare.
	* config/microblaze/microblaze.h (HOT_TEXT_SECTION_NAME,
	UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Remove.
	* config/ia64/hpux.h (HOT_TEXT_SECTION_NAME,
	UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Remove.
	(TARGET_ASM_FUNCTION_SECTION): Define to ia64_hpux_function_section.
	* config/ia64/ia64.c (ia64_hpux_function_section): New function.
	* config/ia64/ia64-protos.h (ia64_hpux_function_section): Define.
	* config/darwin.c (machopic_select_section): Use
	darwin_function_section.
	(darwin_function_section): New function.
	* config/darwin.h (HOT_TEXT_SECTION_NAME,
	UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Remove.
	(TARGET_ASM_FUNCTION_SECTION): Define.
Index: doc/tm.texi
===================================================================
*** doc/tm.texi	(revision 166985)
--- doc/tm.texi	(working copy)
*************** is non-NULL, it is the @code{VAR_DECL} o
*** 7330,7335 ****
--- 7330,7345 ----
  this section is associated.
  @end deftypefn
  
+ @deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_SECTION (tree @var{decl}, enum node_frequency @var{freq}, bool @var{startup}, bool @var{exit})
+ Return preferred text (sub)section for function @var{decl}.
+ Main purpose of this function is to separate cold, normal and hot
+ functions. @var{startup} is true when function is known to be used only 
+ at startup (from static constructors or it is @code{main()}).
+ @var{exit} is true when function is known to be used only at exit
+ (from static destructors).
+ Return NULL if function should go to default text section.
+ @end deftypefn
+ 
  @deftypevr {Target Hook} bool TARGET_HAVE_NAMED_SECTIONS
  This flag is true if the target supports @code{TARGET_ASM_NAMED_SECTION}.
  @end deftypevr
Index: doc/tm.texi.in
===================================================================
*** doc/tm.texi.in	(revision 166985)
--- doc/tm.texi.in	(working copy)
*************** is non-NULL, it is the @code{VAR_DECL} o
*** 7305,7310 ****
--- 7305,7320 ----
  this section is associated.
  @end deftypefn
  
+ @hook TARGET_ASM_FUNCTION_SECTION
+ Return preferred text (sub)section for function @var{decl}.
+ Main purpose of this function is to separate cold, normal and hot
+ functions. @var{startup} is true when function is known to be used only 
+ at startup (from static constructors or it is @code{main()}).
+ @var{exit} is true when function is known to be used only at exit
+ (from static destructors).
+ Return NULL if function should go to default text section.
+ @end deftypefn
+ 
  @hook TARGET_HAVE_NAMED_SECTIONS
  This flag is true if the target supports @code{TARGET_ASM_NAMED_SECTION}.
  @end deftypevr
Index: targhooks.h
===================================================================
*** targhooks.h	(revision 166985)
--- targhooks.h	(working copy)
*************** extern int default_label_align_after_bar
*** 171,177 ****
  extern int default_loop_align_max_skip (rtx);
  extern int default_label_align_max_skip (rtx);
  extern int default_jump_align_max_skip (rtx);
! 
  extern enum machine_mode default_get_reg_raw_mode(int);
  
  extern const struct default_options empty_optimization_table[];
--- 171,178 ----
  extern int default_loop_align_max_skip (rtx);
  extern int default_label_align_max_skip (rtx);
  extern int default_jump_align_max_skip (rtx);
! extern section * default_function_section(tree decl, enum node_frequency freq,
! 					  bool startup, bool exit);
  extern enum machine_mode default_get_reg_raw_mode(int);
  
  extern const struct default_options empty_optimization_table[];
Index: target.def
===================================================================
*** target.def	(revision 166985)
--- target.def	(working copy)
*************** DEFHOOK
*** 281,286 ****
--- 281,299 ----
   void, (const char *name, unsigned int flags, tree decl),
   default_no_named_section)
  
+ /* Return preferred text (sub)section for function DECL.
+    Main purpose of this function is to separate cold, normal and hot
+    functions. STARTUP is true when function is known to be used only 
+    at startup (from static constructors or it is main()).
+    EXIT is true when function is known to be used only at exit
+    (from static destructors).
+    Return NULL if function should go to default text section.  */
+ DEFHOOK
+ (function_section,
+  "",
+  section *, (tree decl, enum node_frequency freq, bool startup, bool exit),
+  default_function_section)
+ 
  /* Return a mask describing how relocations should be treated when
     selecting sections.  Bit 1 should be set if global relocations
     should be placed in a read-write section; bit 0 should be set if
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 166985)
--- cgraph.h	(working copy)
*************** struct GTY(()) cgraph_clone_info
*** 180,199 ****
    bitmap combined_args_to_skip;
  };
  
- enum node_frequency {
-   /* This function most likely won't be executed at all.
-      (set only when profile feedback is available or via function attribute). */
-   NODE_FREQUENCY_UNLIKELY_EXECUTED,
-   /* For functions that are known to be executed once (i.e. constructors, destructors
-      and main function.  */
-   NODE_FREQUENCY_EXECUTED_ONCE,
-   /* The default value.  */
-   NODE_FREQUENCY_NORMAL,
-   /* Optimize this function hard
-      (set only when profile feedback is available or via function attribute). */
-   NODE_FREQUENCY_HOT
- };
- 
  
  /* The cgraph data structure.
     Each function decl has assigned cgraph_node listing callees and callers.  */
--- 180,185 ----
Index: defaults.h
===================================================================
*** defaults.h	(revision 166985)
--- defaults.h	(working copy)
*************** see the files COPYING3 and COPYING.RUNTI
*** 897,910 ****
  #define TARGET_DEC_EVAL_METHOD 2
  #endif
  
- #ifndef HOT_TEXT_SECTION_NAME
- #define HOT_TEXT_SECTION_NAME ".text.hot"
- #endif
- 
- #ifndef UNLIKELY_EXECUTED_TEXT_SECTION_NAME
- #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME ".text.unlikely"
- #endif
- 
  #ifndef HAS_LONG_COND_BRANCH
  #define HAS_LONG_COND_BRANCH 0
  #endif
--- 897,902 ----
Index: tree.h
===================================================================
*** tree.h	(revision 166985)
--- tree.h	(working copy)
*************** struct GTY(()) tree_parm_decl {
*** 3107,3112 ****
--- 3107,3117 ----
  #define DECL_HAS_INIT_PRIORITY_P(NODE) \
    (VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p)
  
+ /* Specify whether the section name was set by user or by
+    compiler via -ffunction-sections.  */
+ #define DECL_HAS_IMPLICIT_SECTION_NAME_P(NODE) \
+   (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.implicit_section_name_p)
+ 
  struct GTY(()) tree_decl_with_vis {
   struct tree_decl_with_rtl common;
   tree assembler_name;
*************** struct GTY(()) tree_decl_with_vis {
*** 3135,3141 ****
   unsigned init_priority_p : 1;
   /* Used by C++ only.  Might become a generic decl flag.  */
   unsigned shadowed_for_var_p : 1;
!  /* 14 unused bits. */
  };
  
  extern tree decl_debug_expr_lookup (tree);
--- 3140,3148 ----
   unsigned init_priority_p : 1;
   /* Used by C++ only.  Might become a generic decl flag.  */
   unsigned shadowed_for_var_p : 1;
!  /* When SECTION_NAME is implied by -ffunsection-section.  */
!  unsigned implicit_section_name_p : 1;
!  /* 13 unused bits. */
  };
  
  extern tree decl_debug_expr_lookup (tree);
Index: predict.c
===================================================================
*** predict.c	(revision 166985)
--- predict.c	(working copy)
*************** static sreal real_zero, real_one, real_a
*** 78,84 ****
  static void combine_predictions_for_insn (rtx, basic_block);
  static void dump_prediction (FILE *, enum br_predictor, int, basic_block, int);
  static void predict_paths_leading_to (basic_block, enum br_predictor, enum prediction);
- static void choose_function_section (void);
  static bool can_predict_insn_p (const_rtx);
  
  /* Information we hold about each branch predictor.
--- 78,83 ----
*************** estimate_bb_frequencies (void)
*** 2185,2192 ****
        free_aux_for_edges ();
      }
    compute_function_frequency ();
-   if (flag_reorder_functions)
-     choose_function_section ();
  }
  
  /* Decide whether function is hot, cold or unlikely executed.  */
--- 2184,2189 ----
*************** compute_function_frequency (void)
*** 2232,2266 ****
      }
  }
  
- /* Choose appropriate section for the function.  */
- static void
- choose_function_section (void)
- {
-   struct cgraph_node *node = cgraph_node (current_function_decl);
-   if (DECL_SECTION_NAME (current_function_decl)
-       || !targetm.have_named_sections
-       /* Theoretically we can split the gnu.linkonce text section too,
- 	 but this requires more work as the frequency needs to match
- 	 for all generated objects so we need to merge the frequency
- 	 of all instances.  For now just never set frequency for these.  */
-       || DECL_ONE_ONLY (current_function_decl))
-     return;
- 
-   /* If we are doing the partitioning optimization, let the optimization
-      choose the correct section into which to put things.  */
- 
-   if (flag_reorder_blocks_and_partition)
-     return;
- 
-   if (node->frequency == NODE_FREQUENCY_HOT)
-     DECL_SECTION_NAME (current_function_decl) =
-       build_string (strlen (HOT_TEXT_SECTION_NAME), HOT_TEXT_SECTION_NAME);
-   if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
-     DECL_SECTION_NAME (current_function_decl) =
-       build_string (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME),
- 		    UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
- }
- 
  static bool
  gate_estimate_probability (void)
  {
--- 2229,2234 ----
Index: function.h
===================================================================
*** function.h	(revision 166985)
--- function.h	(working copy)
*************** struct GTY(()) function_subsections {
*** 226,236 ****
    const char *cold_section_label;
    const char *hot_section_end_label;
    const char *cold_section_end_label;
- 
-   /* String to be used for name of cold text sections, via
-      targetm.asm_out.named_section.  */
- 
-   const char *unlikely_text_section_name;
  };
  
  /* Describe an empty area of space in the stack frame.  These can be chained
--- 226,231 ----
Index: coretypes.h
===================================================================
*** coretypes.h	(revision 166985)
--- coretypes.h	(working copy)
*************** enum unwind_info_type
*** 121,126 ****
--- 121,142 ----
    UI_TARGET
  };
  
+ /* Callgraph node profile representation.  */
+ enum node_frequency {
+   /* This function most likely won't be executed at all.
+      (set only when profile feedback is available or via function attribute). */
+   NODE_FREQUENCY_UNLIKELY_EXECUTED,
+   /* For functions that are known to be executed once (i.e. constructors, destructors
+      and main function.  */
+   NODE_FREQUENCY_EXECUTED_ONCE,
+   /* The default value.  */
+   NODE_FREQUENCY_NORMAL,
+   /* Optimize this function hard
+      (set only when profile feedback is available or via function attribute). */
+   NODE_FREQUENCY_HOT
+ };
+ 
+ 
  struct edge_def;
  typedef struct edge_def *edge;
  typedef const struct edge_def *const_edge;
Index: varasm.c
===================================================================
*** varasm.c	(revision 166985)
--- varasm.c	(working copy)
*************** create_block_symbol (const char *label, 
*** 368,436 ****
    return symbol;
  }
  
- static void
- initialize_cold_section_name (void)
- {
-   const char *stripped_name;
-   char *name, *buffer;
-   tree dsn;
- 
-   gcc_assert (cfun && current_function_decl);
-   if (crtl->subsections.unlikely_text_section_name)
-     return;
- 
-   dsn = DECL_SECTION_NAME (current_function_decl);
-   if (flag_function_sections && dsn)
-     {
-       name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
-       memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1);
- 
-       stripped_name = targetm.strip_name_encoding (name);
- 
-       buffer = ACONCAT ((stripped_name, "_unlikely", NULL));
-       crtl->subsections.unlikely_text_section_name = ggc_strdup (buffer);
-     }
-   else
-     crtl->subsections.unlikely_text_section_name =  UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
- }
- 
- /* Tell assembler to switch to unlikely-to-be-executed text section.  */
- 
- section *
- unlikely_text_section (void)
- {
-   if (cfun)
-     {
-       if (!crtl->subsections.unlikely_text_section_name)
- 	initialize_cold_section_name ();
- 
-       return get_named_section (NULL, crtl->subsections.unlikely_text_section_name, 0);
-     }
-   else
-     return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
- }
- 
- /* When called within a function context, return true if the function
-    has been assigned a cold text section and if SECT is that section.
-    When called outside a function context, return true if SECT is the
-    default cold section.  */
- 
- bool
- unlikely_text_section_p (section *sect)
- {
-   const char *name;
- 
-   if (cfun)
-     name = crtl->subsections.unlikely_text_section_name;
-   else
-     name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
- 
-   return (name
- 	  && sect
- 	  && SECTION_STYLE (sect) == SECTION_NAMED
- 	  && strcmp (name, sect->named.name) == 0);
- }
- 
  /* Return a section with a particular name and with whatever SECTION_*
     flags section_type_flags deems appropriate.  The name of the section
     is taken from NAME if nonnull, otherwise it is taken from DECL's
--- 368,373 ----
*************** resolve_unique_section (tree decl, int r
*** 462,468 ****
        && targetm.have_named_sections
        && (flag_function_or_data_sections
  	  || DECL_ONE_ONLY (decl)))
!     targetm.asm_out.unique_section (decl, reloc);
  }
  
  #ifdef BSS_SECTION_ASM_OP
--- 399,408 ----
        && targetm.have_named_sections
        && (flag_function_or_data_sections
  	  || DECL_ONE_ONLY (decl)))
!     {
!       targetm.asm_out.unique_section (decl, reloc);
!       DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true;
!     }
  }
  
  #ifdef BSS_SECTION_ASM_OP
*************** hot_function_section (tree decl)
*** 539,587 ****
  }
  #endif
  
  /* Return the section for function DECL.
  
     If DECL is NULL_TREE, return the text section.  We can be passed
!    NULL_TREE under some circumstances by dbxout.c at least.  */
  
! section *
! function_section (tree decl)
  {
!   int reloc = 0;
  
!   if (first_function_block_is_cold)
!     reloc = 1;
  
  #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
    if (decl != NULL_TREE
        && DECL_SECTION_NAME (decl) != NULL_TREE)
!     return reloc ? unlikely_text_section ()
! 		 : get_named_section (decl, NULL, 0);
    else
!     return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
  #else
!   return reloc ? unlikely_text_section () : hot_function_section (decl);
  #endif
  }
  
  section *
  current_function_section (void)
  {
! #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
!   if (current_function_decl != NULL_TREE
!       && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
!     return in_cold_section_p ? unlikely_text_section ()
! 			     : get_named_section (current_function_decl,
! 						  NULL, 0);
!   else
!     return targetm.asm_out.select_section (current_function_decl,
! 					   in_cold_section_p,
! 					   DECL_ALIGN (current_function_decl));
! #else
!   return (in_cold_section_p
! 	  ? unlikely_text_section ()
! 	  : hot_function_section (current_function_decl));
! #endif
  }
  
  /* Return the read-only data section associated with function DECL.  */
--- 479,654 ----
  }
  #endif
  
+ /* Return section for TEXT_SECTION_NAME if DECL or DECL_SECTION_NAME (DECL)
+    is NULL.
+ 
+    When DECL_SECTION_NAME is non-NULL and it is implicit section and
+    NAMED_SECTION_SUFFIX is non-NULL, then produce section called
+    concatenate the name with NAMED_SECTION_SUFFIX.
+    Otherwise produce "TEXT_SECTION_NAME.IMPLICIT_NAME".  */
+ 
+ section *
+ get_named_text_section (tree decl,
+ 		        const char *text_section_name,
+ 		        const char *named_section_suffix)
+ {
+   if (decl && DECL_SECTION_NAME (decl))
+     {
+       if (named_section_suffix)
+ 	{
+ 	  tree dsn = DECL_SECTION_NAME (decl);
+ 	  const char *stripped_name;
+ 	  char *name, *buffer;
+ 
+ 	  name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
+ 	  memcpy (name, TREE_STRING_POINTER (dsn),
+ 		  TREE_STRING_LENGTH (dsn) + 1);
+ 
+ 	  stripped_name = targetm.strip_name_encoding (name);
+ 
+ 	  buffer = ACONCAT ((stripped_name, named_section_suffix, NULL));
+ 	  return get_named_section (decl, buffer, 0);
+ 	}
+       else if (DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+ 	{
+ 	  const char *name;
+ 
+ 	  /* Do not try to split gnu_linkonce functions.  This gets somewhat
+ 	     slipperly.  */
+ 	  if (DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP)
+ 	    return NULL;
+ 	  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ 	  name = targetm.strip_name_encoding (name);
+ 	  return get_named_section (decl, ACONCAT ((text_section_name, ".",
+ 				                   name, NULL)), 0);
+ 	}
+       else
+ 	return NULL;
+     }
+   return get_named_section (decl, text_section_name, 0);
+ }
+ 
+ /* Choose named function section based on its frequency.  */
+ 
+ section *
+ default_function_section (tree decl, enum node_frequency freq,
+ 			  bool startup, bool exit)
+ {
+   /* Startup code should go to startup subsection unless it is
+      unlikely executed (this happens especially with function splitting
+      where we can split away unnecesary parts of static constructors.  */
+   if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+     return get_named_text_section (decl, ".text.startup", NULL);
+ 
+   /* Similarly for exit.  */
+   if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+     return get_named_text_section (decl, ".text.exit", NULL);
+ 
+   /* Group cold functions together, similarly for hot code.  */
+   switch (freq)
+     {
+       case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+ 	return get_named_text_section (decl, "text.unlikely", NULL);
+       case NODE_FREQUENCY_HOT:
+ 	return get_named_text_section (decl, "text.hot", NULL);
+       default:
+ 	return NULL;
+     }
+ }
+ 
  /* Return the section for function DECL.
  
     If DECL is NULL_TREE, return the text section.  We can be passed
!    NULL_TREE under some circumstances by dbxout.c at least. 
  
!    If FORCE_COLD is true, return cold function section ignoring
!    the frequency info of cgraph_node.  */
! 
! static section *
! function_section_1 (tree decl, bool force_cold)
  {
!   section *section = NULL;
!   enum node_frequency freq = NODE_FREQUENCY_NORMAL;
!   bool startup = false, exit = false;
  
!   if (decl)
!     {
!       struct cgraph_node *node = cgraph_node (decl);
! 
!       freq = node->frequency;
!       startup = node->only_called_at_startup;
!       exit = node->only_called_at_exit;
!     }
!   if (force_cold)
!     freq = NODE_FREQUENCY_UNLIKELY_EXECUTED;
  
  #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
    if (decl != NULL_TREE
        && DECL_SECTION_NAME (decl) != NULL_TREE)
!     {
!       if (targetm.asm_out.function_section)
! 	section = targetm.asm_out.function_section (decl, freq,
! 						    startup, exit);
!       if (section)
! 	return section;
!       return get_named_section (decl, NULL, 0);
!     }
    else
!     return targetm.asm_out.select_section
! 	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
! 	     DECL_ALIGN (decl));
  #else
!   if (targetm.asm_out.function_section)
!     section = targetm.asm_out.function_section (decl, freq, startup, exit);
!   if (section)
!     return section;
!   return hot_function_section (decl);
  #endif
  }
  
+ /* Return the section for function DECL.
+ 
+    If DECL is NULL_TREE, return the text section.  We can be passed
+    NULL_TREE under some circumstances by dbxout.c at least.  */
+ 
+ section *
+ function_section (tree decl)
+ {
+   /* Handle cases where function splitting code decides
+      to put function entry point into unlikely executed section
+      despite the fact that the function itself is not cold
+      (i.e. it is called rarely but contains a hot loop that is
+      better to live in hot subsection for the code locality).  */
+   return function_section_1 (decl,
+ 			     first_function_block_is_cold);
+ }
+ 
+ /* Return the section for the current function, take IN_COLD_SECTION_P
+    into account.  */
+ 
  section *
  current_function_section (void)
  {
!   return function_section_1 (current_function_decl, in_cold_section_p);
! }
! 
! /* Tell assembler to switch to unlikely-to-be-executed text section.  */
! 
! section *
! unlikely_text_section (void)
! {
!   return function_section_1 (current_function_decl, true);
! }
! 
! /* When called within a function context, return true if the function
!    has been assigned a cold text section and if SECT is that section.
!    When called outside a function context, return true if SECT is the
!    default cold section.  */
! 
! bool
! unlikely_text_section_p (section *sect)
! {
!   return sect == function_section_1 (current_function_decl, true);
  }
  
  /* Return the read-only data section associated with function DECL.  */
*************** assemble_start_function (tree decl, cons
*** 1454,1461 ****
    char tmp_label[100];
    bool hot_label_written = false;
  
-   crtl->subsections.unlikely_text_section_name = NULL;
- 
    first_function_block_is_cold = false;
    if (flag_reorder_blocks_and_partition)
      {
--- 1521,1526 ----
*************** assemble_start_function (tree decl, cons
*** 1513,1528 ****
    else if (DECL_SECTION_NAME (decl))
      {
        /* Calls to function_section rely on first_function_block_is_cold
! 	 being accurate.  The first block may be cold even if we aren't
! 	 doing partitioning, if the entire function was decided by
! 	 choose_function_section (predict.c) to be cold.  */
! 
!       initialize_cold_section_name ();
! 
!       if (crtl->subsections.unlikely_text_section_name
! 	  && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
! 		     crtl->subsections.unlikely_text_section_name) == 0)
! 	first_function_block_is_cold = true;
      }
  
    in_cold_section_p = first_function_block_is_cold;
--- 1578,1587 ----
    else if (DECL_SECTION_NAME (decl))
      {
        /* Calls to function_section rely on first_function_block_is_cold
! 	 being accurate.  */
!       first_function_block_is_cold
! 	 = (cgraph_node (current_function_decl)->frequency
! 	    == NODE_FREQUENCY_UNLIKELY_EXECUTED);
      }
  
    in_cold_section_p = first_function_block_is_cold;
*************** default_section_type_flags (tree decl, c
*** 5871,5885 ****
      flags = SECTION_CODE;
    else if (decl && decl_readonly_section (decl, reloc))
      flags = 0;
-   else if (current_function_decl
- 	   && cfun
- 	   && crtl->subsections.unlikely_text_section_name
- 	   && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
-     flags = SECTION_CODE;
-   else if (!decl
- 	   && (!current_function_decl || !cfun)
- 	   && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
-     flags = SECTION_CODE;
    else
      flags = SECTION_WRITE;
  
--- 5930,5935 ----
*************** switch_to_section (section *new_section)
*** 6810,6821 ****
    switch (SECTION_STYLE (new_section))
      {
      case SECTION_NAMED:
-       if (cfun
- 	  && !crtl->subsections.unlikely_text_section_name
- 	  && strcmp (new_section->named.name,
- 		     UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
- 	crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
- 
        targetm.asm_out.named_section (new_section->named.name,
  				     new_section->named.common.flags,
  				     new_section->named.decl);
--- 6860,6865 ----
Index: output.h
===================================================================
*** output.h	(revision 166985)
--- output.h	(working copy)
*************** extern bool default_assemble_integer (rt
*** 269,274 ****
--- 269,278 ----
     be outputable. */
  extern bool assemble_integer (rtx, unsigned, unsigned, int);
  
+ /* Return section for TEXT_SECITON_NAME if DECL or DECL_SECTION_NAME (DECL)
+    is NULL.  */
+ extern section *get_named_text_section (tree, const char *, const char *);
+ 
  /* An interface to assemble_integer for the common case in which a value is
     fully aligned and must be printed.  VALUE is the value of the integer
     object and SIZE is the number of bytes it contains.  */
Index: config/i386/winnt.c
===================================================================
*** config/i386/winnt.c	(revision 166985)
--- config/i386/winnt.c	(working copy)
*************** i386_pe_section_type_flags (tree decl, c
*** 414,428 ****
      flags = SECTION_CODE;
    else if (decl && decl_readonly_section (decl, reloc))
      flags = 0;
-   else if (current_function_decl
- 	   && cfun
- 	   && crtl->subsections.unlikely_text_section_name
- 	   && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
-     flags = SECTION_CODE;
-   else if (!decl
- 	   && (!current_function_decl || !cfun)
- 	   && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
-     flags = SECTION_CODE;
    else
      {
        flags = SECTION_WRITE;
--- 414,419 ----
Index: config/darwin-protos.h
===================================================================
*** config/darwin-protos.h	(revision 166985)
--- config/darwin-protos.h	(working copy)
*************** extern section *machopic_select_section 
*** 57,62 ****
--- 57,63 ----
  extern section *machopic_select_rtx_section (enum machine_mode, rtx,
  					     unsigned HOST_WIDE_INT);
  
+ extern section *darwin_function_section (tree, enum node_frequency, bool, bool); 
  extern void darwin_unique_section (tree decl, int reloc);
  extern void darwin_asm_named_section (const char *, unsigned int, tree);
  extern void darwin_non_lazy_pcrel (FILE *, rtx);
Index: config/microblaze/microblaze.h
===================================================================
*** config/microblaze/microblaze.h	(revision 166985)
--- config/microblaze/microblaze.h	(working copy)
*************** do {									 \
*** 880,889 ****
  #define SBSS_SECTION_ASM_OP     "\t.sbss"	/* Small RW uninitialized data */
  #define SBSS2_SECTION_ASM_OP    "\t.sbss2"	/* Small RO uninitialized data */
  
- #define HOT_TEXT_SECTION_NAME   ".text.hot"
- #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
-                                 ".text.unlikely"
- 
  /* We do this to save a few 10s of code space that would be taken up
     by the call_FUNC () wrappers, used by the generic CRT_CALL_STATIC_FUNCTION
     definition in crtstuff.c.  */
--- 880,885 ----
Index: config/ia64/ia64.c
===================================================================
*** config/ia64/ia64.c	(revision 166985)
--- config/ia64/ia64.c	(working copy)
*************** ia64_get_reg_raw_mode (int regno)
*** 11021,11024 ****
--- 11021,11035 ----
    return default_get_reg_raw_mode(regno);
  }
  
+ /* Always default to .text section until HP-UX linker is fixed.  */
+ 
+ section *
+ ia64_hpux_function_section (tree decl ATTRIBUTE_UNUSED,
+ 			    enum node_frequency freq ATTRIBUTE_UNUSED,
+ 			    bool startup ATTRIBUTE_UNUSED,
+ 			    bool exit ATTRIBUTE_UNUSED)
+ {
+   return NULL;
+ }
+ 
  #include "gt-ia64.h"
Index: config/ia64/hpux.h
===================================================================
*** config/ia64/hpux.h	(revision 166985)
--- config/ia64/hpux.h	(working copy)
*************** do {								\
*** 221,228 ****
     it is fixed, prevent code from being put into .text.unlikely or
     .text.hot.  */
  
! #undef UNLIKELY_EXECUTED_TEXT_SECTION_NAME
! #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME ".text"
! 
! #undef HOT_TEXT_SECTION_NAME
! #define HOT_TEXT_SECTION_NAME ".text"
--- 221,224 ----
     it is fixed, prevent code from being put into .text.unlikely or
     .text.hot.  */
  
! #define TARGET_ASM_FUNCTION_SECTION ia64_hpux_function_section
Index: config/ia64/ia64-protos.h
===================================================================
*** config/ia64/ia64-protos.h	(revision 166985)
--- config/ia64/ia64-protos.h	(working copy)
*************** extern void ia64_init_expanders (void);
*** 97,99 ****
--- 97,100 ----
  
  extern rtx ia64_dconst_0_5 (void);
  extern rtx ia64_dconst_0_375 (void);
+ extern section *ia64_hpux_function_section (decl, enum node_frequency, startup, exit);
Index: config/darwin.c
===================================================================
*** config/darwin.c	(revision 166985)
--- config/darwin.c	(working copy)
*************** machopic_select_section (tree decl,
*** 1233,1244 ****
  	       && DECL_WEAK (decl)
  	       && !lookup_attribute ("weak_import",
  				     DECL_ATTRIBUTES (decl)));
!   section *base_section;
  
    switch (categorize_decl_for_section (decl, reloc))
      {
      case SECCAT_TEXT:
!       base_section = darwin_text_section (reloc, weak);
        break;
  
      case SECCAT_RODATA:
--- 1233,1254 ----
  	       && DECL_WEAK (decl)
  	       && !lookup_attribute ("weak_import",
  				     DECL_ATTRIBUTES (decl)));
!   section *base_section = NULL;
  
    switch (categorize_decl_for_section (decl, reloc))
      {
      case SECCAT_TEXT:
!       {
! 	struct cgraph_node *node;
! 	if (decl && TREE_CODE (decl) == FUNCTION_DECL
! 	    && (node = cgraph_get_node (decl)) != NULL)
! 	  base_section = darwin_function_section (decl,
! 						  node->frequency,
! 						  node->only_called_at_startup,
! 						  node->only_called_at_exit);
! 	if (!base_section)
!           base_section = darwin_text_section (reloc, weak);
!       }
        break;
  
      case SECCAT_RODATA:
*************** darwin_enter_string_into_cfstring_table 
*** 2362,2365 ****
--- 2372,2409 ----
      }
  }
  
+ /* Choose named function section based on its frequency.  */
+ 
+ section *
+ darwin_function_section (tree decl, enum node_frequency freq,
+ 			  bool startup, bool exit)
+ {
+   /* Startup code should go to startup subsection unless it is
+      unlikely executed (this happens especially with function splitting
+      where we can split away unnecesary parts of static constructors.  */
+   if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+     return get_named_text_section
+ 	     (decl, "__TEXT,__startup,regular,pure_instructions", "_startup");
+ 
+   /* Similarly for exit.  */
+   if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+     return get_named_text_section (decl,
+ 				   "__TEXT,__exit,regular,pure_instructions",
+ 				   "_exit");
+ 
+   /* Group cold functions together, similarly for hot code.  */
+   switch (freq)
+     {
+       case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+ 	return get_named_text_section
+ 		 (decl,
+ 	          "__TEXT,__unlikely,regular,pure_instructions", "_ulinkely");
+       case NODE_FREQUENCY_HOT:
+ 	return get_named_text_section
+ 		 (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
+       default:
+ 	return NULL;
+     }
+ }
+ 
  #include "gt-darwin.h"
Index: config/darwin.h
===================================================================
*** config/darwin.h	(revision 166985)
--- config/darwin.h	(working copy)
*************** int darwin_label_is_anonymous_local_objc
*** 658,668 ****
  /* The generic version, archs should over-ride where required.  */
  #define MACHOPIC_NL_SYMBOL_PTR_SECTION ".non_lazy_symbol_pointer"
  
- /* These are used by -fbranch-probabilities */
- #define HOT_TEXT_SECTION_NAME "__TEXT,__text,regular,pure_instructions"
- #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
-                               "__TEXT,__unlikely,regular,pure_instructions"
- 
  /* Declare the section variables.  */
  #ifndef USED_FOR_TARGET
  enum darwin_section_enum {
--- 658,663 ----
*************** extern GTY(()) section * darwin_sections
*** 677,682 ****
--- 672,679 ----
  #undef	TARGET_ASM_SELECT_SECTION
  #define TARGET_ASM_SELECT_SECTION machopic_select_section
  #define USE_SELECT_SECTION_FOR_FUNCTIONS
+ #undef	TARGET_ASM_FUNCTION_SECTION
+ #define TARGET_ASM_FUNCTION_SECTION darwin_function_section
  
  #undef	TARGET_ASM_SELECT_RTX_SECTION
  #define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section


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