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


On Sun, Nov 21, 2010 at 02:12:43AM +0100, Jan Hubicka wrote:
> 
> 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,
   No problems after bootstrapping and regression testing on x86_64-apple-darwin10.

http://gcc.gnu.org/ml/gcc-testresults/2010-11/msg01764.html

Of course I am still having to hack around PR46510.
              Jack

> 
> 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]