diff mbox

Group static constructors and destructors in specific subsections, take 2

Message ID 20101110042452.GA2722@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Nov. 10, 2010, 4:24 a.m. UTC
Hi,
this is the updated patch that deals with section instead of section names as
Richard requested and also uses hook instead of target macros.
The hot/cold function partitioning made things somewhat harder since we have
special code for cold sections all around.

Baic idea is to have named_text_subsection to produce subsections for functions
in generic way and function_section hook to decide proper subsection based on
profile.

I've bootstrapped/regtested the patch on x86_64-linux, I also checked that Hpux
and dwarf output seems sane at a glance.

Does the patch seem resonable?

Honza
	* 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.
	(subsection_hash): New static var.
	(eq_subsections): New function.
	(hash_subsection): New function.
	(named_text_subsection): 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 (named_text_subsection): 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_SECTOIN): Define to NULL.
	* 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.

Comments

Jack Howarth Nov. 10, 2010, 2:15 p.m. UTC | #1
On Wed, Nov 10, 2010 at 05:24:52AM +0100, Jan Hubicka wrote:
> Hi,
> this is the updated patch that deals with section instead of section names as
> Richard requested and also uses hook instead of target macros.
> The hot/cold function partitioning made things somewhat harder since we have
> special code for cold sections all around.
> 
> Baic idea is to have named_text_subsection to produce subsections for functions
> in generic way and function_section hook to decide proper subsection based on
> profile.
> 
> I've bootstrapped/regtested the patch on x86_64-linux, I also checked that Hpux
> and dwarf output seems sane at a glance.

Honza,
   This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...

makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
make[3]: *** [doc/gccint.info] Error 1
make[3]: *** Waiting for unfinished jobs....

           Jack
> 
> Does the patch seem resonable?
> 
> Honza
> 	* 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.
> 	(subsection_hash): New static var.
> 	(eq_subsections): New function.
> 	(hash_subsection): New function.
> 	(named_text_subsection): 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 (named_text_subsection): 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_SECTOIN): Define to NULL.
> 	* 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 166490)
> +++ doc/tm.texi	(working copy)
> @@ -7335,6 +7335,8 @@ macro is not defined, nothing is output 
>  @end defmac
>  
>  @deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags}, tree @var{decl})
> +
> +@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_SECTION (tree @var{decl}, enum node_frequency @var{freq}, bool @var{startup}, bool @var{exit})
>  Output assembly directives to switch to section @var{name}.  The section
>  should have attributes as specified by @var{flags}, which is a bit mask
>  of the @code{SECTION_*} flags defined in @file{output.h}.  If @var{decl}
> Index: targhooks.h
> ===================================================================
> --- targhooks.h	(revision 166490)
> +++ targhooks.h	(working copy)
> @@ -169,7 +169,8 @@ extern int default_label_align_after_bar
>  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 166490)
> +++ target.def	(working copy)
> @@ -281,6 +281,19 @@ DEFHOOK
>   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 166490)
> +++ cgraph.h	(working copy)
> @@ -179,20 +179,6 @@ struct GTY(()) cgraph_clone_info
>    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.  */
> Index: defaults.h
> ===================================================================
> --- defaults.h	(revision 166490)
> +++ defaults.h	(working copy)
> @@ -897,14 +897,6 @@ see the files COPYING3 and COPYING.RUNTI
>  #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
> Index: predict.c
> ===================================================================
> --- predict.c	(revision 166490)
> +++ predict.c	(working copy)
> @@ -78,7 +78,6 @@ static sreal real_zero, real_one, real_a
>  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.
> @@ -2185,8 +2184,6 @@ estimate_bb_frequencies (void)
>        free_aux_for_edges ();
>      }
>    compute_function_frequency ();
> -  if (flag_reorder_functions)
> -    choose_function_section ();
>  }
>  
>  /* Decide whether function is hot, cold or unlikely executed.  */
> @@ -2232,35 +2229,6 @@ compute_function_frequency (void)
>      }
>  }
>  
> -/* 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)
>  {
> Index: function.h
> ===================================================================
> --- function.h	(revision 166490)
> +++ function.h	(working copy)
> @@ -226,11 +226,6 @@ struct GTY(()) function_subsections {
>    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
> Index: coretypes.h
> ===================================================================
> --- coretypes.h	(revision 166490)
> +++ coretypes.h	(working copy)
> @@ -121,6 +121,22 @@ enum unwind_info_type
>    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 166490)
> +++ varasm.c	(working copy)
> @@ -368,69 +368,6 @@ create_block_symbol (const char *label, 
>    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
> @@ -539,49 +476,202 @@ hot_function_section (tree decl)
>  }
>  #endif
>  
> +/* Hash table used to cache names of function subsections.  */
> +struct GTY(()) named_subsection_entry
> +{
> +  section *sect;
> +  tree section_name;
> +  const char *suffix;
> +};
> +
> +static GTY((param_is (struct named_subsection_entry))) htab_t subsection_hash;
> +
> +/* Returns nonzero if P1 and P2 are equal.  */
> +
> +static int
> +eq_subsections (const void *p1, const void *p2)
> +{
> +  const struct named_subsection_entry *n1 = (const struct named_subsection_entry *) p1;
> +  const struct named_subsection_entry *n2 = (const struct named_subsection_entry *) p2;
> +  return n1->section_name == n2->section_name && n1->suffix == n2->suffix;
> +}
> +
> +/* Compute hash value of subsection.  */
> +static unsigned int
> +hash_subsection (const void *p)
> +{
> +  const struct named_subsection_entry *n = (const struct named_subsection_entry *)p;
> +  return htab_hash_pointer (n->section_name) ^ htab_hash_pointer (n->suffix);
> +}
> +
> +/* Return section for TEXT_SECITON_NAME if DECL or DECL_SECTION_NAME (DECL)
> +   is NULL.
> +
> +   If it is non-NULL, return subsection of DECL_SECTION_NAME (DECL) created
> +   by appending NAMED_SECTION_SUFFIX.  */
> +
> +section *
> +named_text_subsection (tree decl,
> +		       const char *text_section_name,
> +		       const char *named_section_suffix)
> +{
> +  if (decl && DECL_SECTION_NAME (decl))
> +    {
> +      tree dsn = DECL_SECTION_NAME (decl);
> +      struct named_subsection_entry key, *entry, **slot;
> +
> +      key.suffix = named_section_suffix;
> +      key.section_name = dsn;
> +      if (!subsection_hash)
> +	subsection_hash =
> +	  htab_create_ggc (10, hash_subsection, eq_subsections, NULL);
> +      slot =
> +	(struct named_subsection_entry **) htab_find_slot (subsection_hash,
> +							   &key, INSERT);
> +      if (!*slot)
> +	{
> +	  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));
> +	  entry = ggc_alloc_named_subsection_entry ();
> +	  entry->section_name = dsn;
> +	  entry->suffix = named_section_suffix;
> +	  entry->sect = get_named_section (decl, buffer, 0);
> +	  *slot = entry;
> +	}
> +      return (*slot)->sect;
> +    }
> +  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 named_text_subsection (decl, ".text.startup", "_startup");
> +
> +  /* Similarly for exit.  */
> +  if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
> +    return named_text_subsection (decl, ".text.exit", "_exit");
> +
> +  /* Group cold functions together, similarly for hot code.  */
> +  switch (freq)
> +    {
> +      case NODE_FREQUENCY_UNLIKELY_EXECUTED:
> +	return named_text_subsection (decl, "text.unlikely", "_unlikely");
> +      case NODE_FREQUENCY_HOT:
> +	return named_text_subsection (decl, "text.hot", "_hot");
> +      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.  */
> +   NULL_TREE under some circumstances by dbxout.c at least. 
>  
> -section *
> -function_section (tree decl)
> +   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)
>  {
> -  int reloc = 0;
> +  section *section = NULL;
> +  enum node_frequency freq = NODE_FREQUENCY_NORMAL;
> +  bool startup = false, exit = false;
>  
> -  if (first_function_block_is_cold)
> -    reloc = 1;
> +  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)
> -    return reloc ? unlikely_text_section ()
> -		 : get_named_section (decl, NULL, 0);
> +    {
> +      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, reloc, DECL_ALIGN (decl));
> +    return targetm.asm_out.select_section
> +	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
> +	     DECL_ALIGN (decl));
>  #else
> -  return reloc ? unlikely_text_section () : hot_function_section (decl);
> +  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
> +		             && flag_function_sections);
> +}
> +
> +/* Return the section for the current function, take IN_COLD_SECTION_P
> +   into account.  */
> +
>  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 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.  */
> @@ -1483,16 +1573,10 @@ assemble_start_function (tree decl, cons
>    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;
> +	 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;
> @@ -5841,15 +5925,6 @@ default_section_type_flags (tree decl, c
>      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;
>  
> @@ -6776,12 +6851,6 @@ switch_to_section (section *new_section)
>    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);
> Index: output.h
> ===================================================================
> --- output.h	(revision 166490)
> +++ output.h	(working copy)
> @@ -264,6 +264,10 @@ extern bool default_assemble_integer (rt
>     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 *named_text_subsection (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 166490)
> +++ config/i386/winnt.c	(working copy)
> @@ -414,15 +414,6 @@ i386_pe_section_type_flags (tree decl, c
>      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;
> Index: config/darwin-protos.h
> ===================================================================
> --- config/darwin-protos.h	(revision 166490)
> +++ config/darwin-protos.h	(working copy)
> @@ -57,6 +57,7 @@ extern section *machopic_select_section 
>  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 166490)
> +++ config/microblaze/microblaze.h	(working copy)
> @@ -880,10 +880,6 @@ do {									 \
>  #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.  */
> Index: config/ia64/hpux.h
> ===================================================================
> --- config/ia64/hpux.h	(revision 166490)
> +++ config/ia64/hpux.h	(working copy)
> @@ -221,8 +221,4 @@ do {								\
>     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"
> +#define TARGET_ASM_FUNCTION_SECTOIN NULL
> Index: config/darwin.c
> ===================================================================
> --- config/darwin.c	(revision 166490)
> +++ config/darwin.c	(working copy)
> @@ -1233,12 +1233,22 @@ machopic_select_section (tree decl,
>  	       && DECL_WEAK (decl)
>  	       && !lookup_attribute ("weak_import",
>  				     DECL_ATTRIBUTES (decl)));
> -  section *base_section;
> +  section *base_section = NULL;
>  
>    switch (categorize_decl_for_section (decl, reloc))
>      {
>      case SECCAT_TEXT:
> -      base_section = darwin_text_section (reloc, weak);
> +      {
> +	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:
> @@ -2362,4 +2372,38 @@ darwin_enter_string_into_cfstring_table 
>      }
>  }
>  
> +/* 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 named_text_subsection
> +	     (decl, "__TEXT,__startup,regular,pure_instructions", "_startup");
> +
> +  /* Similarly for exit.  */
> +  if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
> +    return named_text_subsection (decl,
> +				  "__TEXT,__exit,regular,pure_instructions",
> +				  "_exit");
> +
> +  /* Group cold functions together, similarly for hot code.  */
> +  switch (freq)
> +    {
> +      case NODE_FREQUENCY_UNLIKELY_EXECUTED:
> +	return named_text_subsection
> +		 (decl,
> +	          "__TEXT,__unlikely,regular,pure_instructions", "_ulinkely");
> +      case NODE_FREQUENCY_HOT:
> +	return named_text_subsection
> +		 (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
> +      default:
> +	return NULL;
> +    }
> +}
> +
>  #include "gt-darwin.h"
> Index: config/darwin.h
> ===================================================================
> --- config/darwin.h	(revision 166490)
> +++ config/darwin.h	(working copy)
> @@ -710,11 +710,6 @@ int darwin_label_is_anonymous_local_objc
>  /* 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 {
> @@ -729,6 +724,8 @@ extern GTY(()) section * darwin_sections
>  #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
Ian Lance Taylor Nov. 10, 2010, 2:54 p.m. UTC | #2
Jack Howarth <howarth@bromo.med.uc.edu> writes:

>    This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...
>
> makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
> gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
> 		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
> make[3]: *** [doc/gccint.info] Error 1
> make[3]: *** Waiting for unfinished jobs....

That's not the error, that's just the part which says that there were
errors.  There should be more output from makeinfo earlier in the log
which shows the real error.

Ian
Jack Howarth Nov. 10, 2010, 2:58 p.m. UTC | #3
On Wed, Nov 10, 2010 at 06:54:50AM -0800, Ian Lance Taylor wrote:
> Jack Howarth <howarth@bromo.med.uc.edu> writes:
> 
> >    This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...
> >
> > makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
> > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
> > 		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
> > make[3]: *** [doc/gccint.info] Error 1
> > make[3]: *** Waiting for unfinished jobs....
> 
> That's not the error, that's just the part which says that there were
> errors.  There should be more output from makeinfo earlier in the log
> which shows the real error.
> 
> Ian

Ian,
   Opps. Looks like the real error may be...

# make
[ -f stage_final ] || echo stage3 > stage_final
rm -f stage_current
make[4]: Nothing to be done for `all'.
make[3]: Nothing to be done for `all'.
make[4]: Nothing to be done for `all'.
make[3]: Nothing to be done for `all'.
make[3]: Nothing to be done for `all'.
make[3]: Nothing to be done for `all'.
gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/. -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include ../../gcc-4.6-20101110/gcc/varasm.c -o varasm.o
../../gcc-4.6-20101110/gcc/varasm.c: In function 'assemble_start_function':
../../gcc-4.6-20101110/gcc/varasm.c:1517: error: 'struct function_subsections' has no member named 'unlikely_text_section_name'
../../gcc-4.6-20101110/gcc/varasm.c: In function 'output_constructor_bitfield':
../../gcc-4.6-20101110/gcc/varasm.c:4832: warning: unknown conversion type character 'E' in format
../../gcc-4.6-20101110/gcc/varasm.c:4832: warning: too many arguments for format
../../gcc-4.6-20101110/gcc/varasm.c: In function 'finish_aliases_1':
../../gcc-4.6-20101110/gcc/varasm.c:5610: warning: unknown conversion type character 'E' in format
../../gcc-4.6-20101110/gcc/varasm.c:5610: warning: too many arguments for format
../../gcc-4.6-20101110/gcc/varasm.c:5624: warning: unknown conversion type character 'E' in format
../../gcc-4.6-20101110/gcc/varasm.c:5624: warning: too many arguments for format
make[3]: *** [varasm.o] Error 1
make[2]: *** [all-stage1-gcc] Error 2
make[1]: *** [stage1-bubble] Error 2
make: *** [all] Error 2
Jan Hubicka Nov. 10, 2010, 3:27 p.m. UTC | #4
> On Wed, Nov 10, 2010 at 06:54:50AM -0800, Ian Lance Taylor wrote:
> > Jack Howarth <howarth@bromo.med.uc.edu> writes:
> > 
> > >    This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...
> > >
> > > makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
> > > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
> > > 		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
> > > make[3]: *** [doc/gccint.info] Error 1
> > > make[3]: *** Waiting for unfinished jobs....
> > 
> > That's not the error, that's just the part which says that there were
> > errors.  There should be more output from makeinfo earlier in the log
> > which shows the real error.
> > 
> > Ian
> 
> Ian,
>    Opps. Looks like the real error may be...
> 
> # make
> [ -f stage_final ] || echo stage3 > stage_final
> rm -f stage_current
> make[4]: Nothing to be done for `all'.
> make[3]: Nothing to be done for `all'.
> make[4]: Nothing to be done for `all'.
> make[3]: Nothing to be done for `all'.
> make[3]: Nothing to be done for `all'.
> make[3]: Nothing to be done for `all'.
> gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/. -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include ../../gcc-4.6-20101110/gcc/varasm.c -o varasm.o
> ../../gcc-4.6-20101110/gcc/varasm.c: In function 'assemble_start_function':
> ../../gcc-4.6-20101110/gcc/varasm.c:1517: error: 'struct function_subsections' has no member named 'unlikely_text_section_name'

Oops, can you, please, try again with the statement at line 1517:
 crtl->subsections.unlikely_text_section_name = NULL
removed?
I checked that this is last occurence of this and updated my local patch.

Thanks for testing it!

Honza
Jack Howarth Nov. 10, 2010, 4:43 p.m. UTC | #5
On Wed, Nov 10, 2010 at 04:27:17PM +0100, Jan Hubicka wrote:
> > On Wed, Nov 10, 2010 at 06:54:50AM -0800, Ian Lance Taylor wrote:
> > > Jack Howarth <howarth@bromo.med.uc.edu> writes:
> > > 
> > > >    This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...
> > > >
> > > > makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
> > > > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
> > > > 		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
> > > > make[3]: *** [doc/gccint.info] Error 1
> > > > make[3]: *** Waiting for unfinished jobs....
> > > 
> > > That's not the error, that's just the part which says that there were
> > > errors.  There should be more output from makeinfo earlier in the log
> > > which shows the real error.
> > > 
> > > Ian
> > 
> > Ian,
> >    Opps. Looks like the real error may be...
> > 
> > # make
> > [ -f stage_final ] || echo stage3 > stage_final
> > rm -f stage_current
> > make[4]: Nothing to be done for `all'.
> > make[3]: Nothing to be done for `all'.
> > make[4]: Nothing to be done for `all'.
> > make[3]: Nothing to be done for `all'.
> > make[3]: Nothing to be done for `all'.
> > make[3]: Nothing to be done for `all'.
> > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/. -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include ../../gcc-4.6-20101110/gcc/varasm.c -o varasm.o
> > ../../gcc-4.6-20101110/gcc/varasm.c: In function 'assemble_start_function':
> > ../../gcc-4.6-20101110/gcc/varasm.c:1517: error: 'struct function_subsections' has no member named 'unlikely_text_section_name'
> 
> Oops, can you, please, try again with the statement at line 1517:
>  crtl->subsections.unlikely_text_section_name = NULL
> removed?
> I checked that this is last occurence of this and updated my local patch.
> 
> Thanks for testing it!
> 
> Honza

Honza,
   With the line containing...

crtl->subsections.unlikely_text_section_name = NULL

in gcc/varasm.c removed. the failure now moved to...

if [ xinfo = xinfo ]; then \
		makeinfo --split-size=5000000 --split-size=5000000 --split-size=5000000 --no-split -I . -I ../../gcc-4.6-20101110/gcc/doc \
			-I ../../gcc-4.6-20101110/gcc/doc/include -o doc/gccint.info ../../gcc-4.6-20101110/gcc/doc/gccint.texi; \
	fi
../../gcc-4.6-20101110/gcc/doc//tm.texi:7318: No matching `@end deftypefn'.
makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
make[3]: *** [doc/gccint.info] Error 1
make[2]: *** [all-stage1-gcc] Error 2
make[1]: *** [stage1-bubble] Error 2
make: *** [all] Error 2

            Jack
Jan Hubicka Nov. 10, 2010, 5:04 p.m. UTC | #6
> On Wed, Nov 10, 2010 at 04:27:17PM +0100, Jan Hubicka wrote:
> > > On Wed, Nov 10, 2010 at 06:54:50AM -0800, Ian Lance Taylor wrote:
> > > > Jack Howarth <howarth@bromo.med.uc.edu> writes:
> > > > 
> > > > >    This patch is causing a bootstrap failure on x86_64-apple-darwin10 with the error...
> > > > >
> > > > > makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.
> > > > > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -DGENERATOR_FILE -I. -Ibuild -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/build -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include \
> > > > > 		-o build/gencodes.o ../../gcc-4.6-20101110/gcc/gencodes.c
> > > > > make[3]: *** [doc/gccint.info] Error 1
> > > > > make[3]: *** Waiting for unfinished jobs....
> > > > 
> > > > That's not the error, that's just the part which says that there were
> > > > errors.  There should be more output from makeinfo earlier in the log
> > > > which shows the real error.
> > > > 
> > > > Ian
> > > 
> > > Ian,
> > >    Opps. Looks like the real error may be...
> > > 
> > > # make
> > > [ -f stage_final ] || echo stage3 > stage_final
> > > rm -f stage_current
> > > make[4]: Nothing to be done for `all'.
> > > make[3]: Nothing to be done for `all'.
> > > make[4]: Nothing to be done for `all'.
> > > make[3]: Nothing to be done for `all'.
> > > make[3]: Nothing to be done for `all'.
> > > make[3]: Nothing to be done for `all'.
> > > gcc -c   -g -fkeep-inline-functions -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -fno-common  -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.6-20101110/gcc -I../../gcc-4.6-20101110/gcc/. -I../../gcc-4.6-20101110/gcc/../include -I../../gcc-4.6-20101110/gcc/../libcpp/include -I/sw/include -I/sw/include  -I../../gcc-4.6-20101110/gcc/../libdecnumber -I../../gcc-4.6-20101110/gcc/../libdecnumber/dpd -I../libdecnumber -I/sw/include  -I/sw/include -DCLOOG_PPL_BACKEND  -I/sw/include ../../gcc-4.6-20101110/gcc/varasm.c -o varasm.o
> > > ../../gcc-4.6-20101110/gcc/varasm.c: In function 'assemble_start_function':
> > > ../../gcc-4.6-20101110/gcc/varasm.c:1517: error: 'struct function_subsections' has no member named 'unlikely_text_section_name'
> > 
> > Oops, can you, please, try again with the statement at line 1517:
> >  crtl->subsections.unlikely_text_section_name = NULL
> > removed?
> > I checked that this is last occurence of this and updated my local patch.
> > 
> > Thanks for testing it!
> > 
> > Honza
> 
> Honza,
>    With the line containing...
> 
> crtl->subsections.unlikely_text_section_name = NULL
> 
> in gcc/varasm.c removed. the failure now moved to...
> 
> if [ xinfo = xinfo ]; then \
> 		makeinfo --split-size=5000000 --split-size=5000000 --split-size=5000000 --no-split -I . -I ../../gcc-4.6-20101110/gcc/doc \
> 			-I ../../gcc-4.6-20101110/gcc/doc/include -o doc/gccint.info ../../gcc-4.6-20101110/gcc/doc/gccint.texi; \
> 	fi
> ../../gcc-4.6-20101110/gcc/doc//tm.texi:7318: No matching `@end deftypefn'.
> makeinfo: Removing output file `doc/gccint.info' due to errors; use --force to preserve.

Makefile now has this funny message of copying tm.texi.in into tm.texi.  It seems that you copied
doc/tm.texi.in into doc/tm.texi while you need to copy tm.texi.in from your build directory.

Honza
Jan Hubicka Nov. 10, 2010, 5:13 p.m. UTC | #7
> Makefile now has this funny message of copying tm.texi.in into tm.texi.  It seems that you copied
> doc/tm.texi.in into doc/tm.texi while you need to copy tm.texi.in from your build directory.

You can also just revert the doc directory change.  It needs no testing on multiple targets.

Thanks for doing the Darwin run BTW :)
Honza
> 
> Honza
Richard Henderson Nov. 10, 2010, 6:20 p.m. UTC | #8
On 11/09/2010 08:24 PM, Jan Hubicka wrote:
> Index: config/ia64/hpux.h
> ===================================================================
> --- config/ia64/hpux.h	(revision 166490)
> +++ config/ia64/hpux.h	(working copy)
> @@ -221,8 +221,4 @@ do {								\
>     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"
> +#define TARGET_ASM_FUNCTION_SECTOIN NULL

Typo.  But I'd rather avoid a check for NULL that affects only one target.
Better to define a function that does what you want.

>  #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);
> +    {
> +      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, reloc, DECL_ALIGN (decl));
> +    return targetm.asm_out.select_section
> +	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
> +	     DECL_ALIGN (decl));
>  #else
> -  return reloc ? unlikely_text_section () : hot_function_section (decl);
> +  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

Honestly, adding the function_section hook is an excellent opportunity
to get rid of the USE_SELECT_SECTION_FOR_FUNCTIONS macro, used only by
darwin and the MEP port.

I think this whole section should boil down to 

  return targetm.asm_out.function_section (decl, freq, startup, exit);

with the associated ugliness above pushed into various versions of the
function_section hook.

Also, I think hot_function_section should be merged here, so that we're
properly checking for DECL_SECTION_NAME before deferring to the new
function_section hook.  Which means that the hook will either gen up
a new section name based on (freq,startup,exit), or return text_section.

> +section *
> +named_text_subsection (tree decl,
> +		       const char *text_section_name,
> +		       const char *named_section_suffix)

I don't understand why you're bothering to hash the section here, when
that would also be done inside get_section.  Seems like it'd be just as
easy to concat the section name you want and defer the rest to the 
existing functions.

Also, I think get_named_text_section is a better name, in line with the
related functions.

Also, I wonder about the naming of these sections.  Why would we prefer
".text.foo_unlikely" rather than ".text.unlikely.foo"?  It seems to me that 
have the possibility of conflict between a function foo (which is unlikely),
and a function foo_unlikely (which happens to not be unlikely and so not
receive a suffix).

Also, it appears we're doing some amount of section switching even for
functions that have had their DECL_SECTION_NAME set by the user.  We don't
seem to be distinguishing between user settings and settings that came
from resolve_unique_section.  It seems to me that we should *never* change
the section when the user has specified one.

I realize that these last two are pre-existing conditions, but previously
would only be encountered with flag_reorder_blocks_and_partition.  You're
now planning changes that would take effect by default, which seems likely
to break kernels.

Which leads me to wonder if a new hash *is* called for, but would simply
be a map from decl to hot+cold section objects.  Perhaps

static section *
function_section_1 (tree decl, bool force_cold)
{
  slot = decl in hash;
  if (slot)
    {
      sec = is_cold ? slot->cold : slot->hot;
      if (sec)
	return sec;
    }
  else
    slot = new hash entry;

  if (targetm.have_named_sections)
    {
      if (DECL_SECTION_NAME (decl))
        {
          // The user has setup a section for the function.  Honor it.
          sec = get_named_section (decl, NULL, 0);
        }
      else if (DECL_ONE_ONLY (decl))
        {
          // The function must be placed in a comdat section.  Lest we
          // fail to merge duplicates, the section name is part of the
          // ABI of the function.  Don't do hot/cold splitting or other
          // sorts of renames.
	  // ??? Note that this still sets DECL_SECTION_NAME; ideally
	  // we'd revise the interface to return a section, but it's
	  // not critical.
          targetm.asm_out.unique_section (decl, false);
          sec = get_named_section (decl, NULL, 0);
	}
    }
  if (!sec)
    {
      // The hook handles all of the details of hot/cold/startup/exit.
      // It must *not* set DECL_SECTION_NAME, so that when we return
      // for the !is_cold section we arrive here and don't get confused
      // by the cases above.
      sec = targetm.asm_out.function_section (...);
    }

  if (is_cold)
    slot->cold = sec;
  else
    slot->hot = sec;

  return sec;
}



r~
Jan Hubicka Nov. 10, 2010, 7:30 p.m. UTC | #9
> > -#undef HOT_TEXT_SECTION_NAME
> > -#define HOT_TEXT_SECTION_NAME ".text"
> > +#define TARGET_ASM_FUNCTION_SECTOIN NULL
> 
> Typo.  But I'd rather avoid a check for NULL that affects only one target.
> Better to define a function that does what you want.
OK, will do.  Basically it should return NULL.
> 
> >  #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);
> > +    {
> > +      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, reloc, DECL_ALIGN (decl));
> > +    return targetm.asm_out.select_section
> > +	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
> > +	     DECL_ALIGN (decl));
> >  #else
> > -  return reloc ? unlikely_text_section () : hot_function_section (decl);
> > +  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
> 
> Honestly, adding the function_section hook is an excellent opportunity
> to get rid of the USE_SELECT_SECTION_FOR_FUNCTIONS macro, used only by
> darwin and the MEP port.

Hmm, yep, I was looking into that too, but it seems better to do this incrementally
rather than keep snowballing this.
> 
> I think this whole section should boil down to 
> 
>   return targetm.asm_out.function_section (decl, freq, startup, exit);
> 
> with the associated ugliness above pushed into various versions of the
> function_section hook.
> 
> Also, I think hot_function_section should be merged here, so that we're
> properly checking for DECL_SECTION_NAME before deferring to the new
> function_section hook.  Which means that the hook will either gen up
> a new section name based on (freq,startup,exit), or return text_section.
> 
> > +section *
> > +named_text_subsection (tree decl,
> > +		       const char *text_section_name,
> > +		       const char *named_section_suffix)
> 
> I don't understand why you're bothering to hash the section here, when
> that would also be done inside get_section.  Seems like it'd be just as
> easy to concat the section name you want and defer the rest to the 
> existing functions.

Well, I wanted to avoid the string operations because old code did that
too.  We can switch quite few times when doing BB splitting, but I guess
it is non-critical whether we will always concatenate or whether we will
cache in hash.  I can get rid of it definitly.
> 
> Also, I think get_named_text_section is a better name, in line with the
> related functions.
OK.  I use subsection because...
> 
> Also, I wonder about the naming of these sections.  Why would we prefer
> ".text.foo_unlikely" rather than ".text.unlikely.foo"?  It seems to me that 
> have the possibility of conflict between a function foo (which is unlikely),
> and a function foo_unlikely (which happens to not be unlikely and so not
> receive a suffix).

Hmm, this was again copied from old code.  I
> 
> Also, it appears we're doing some amount of section switching even for
> functions that have had their DECL_SECTION_NAME set by the user.  We don't
> seem to be distinguishing between user settings and settings that came
> from resolve_unique_section.  It seems to me that we should *never* change
> the section when the user has specified one.

... while i was glancing over this I believed that it is supposed to work
in a way that when user specify named section "foo", we will create
foo._unlikely/foo._hot ... etc subsection so if there are multiple functions in
the same section they willbe properly grouped within that function.
> 
> I realize that these last two are pre-existing conditions, but previously
> would only be encountered with flag_reorder_blocks_and_partition.  You're
> now planning changes that would take effect by default, which seems likely
> to break kernels.

We used to produce cold functions automatically since ipa-profile got in.
> 
> Which leads me to wonder if a new hash *is* called for, but would simply
> be a map from decl to hot+cold section objects.  Perhaps

I was trying to avoid too much assumptions that we break up into hot/cold
only since it makes sense to do more partitioning and there is no need
to spread this across the code.  But this would work with me, too.

Honza
> 
> static section *
> function_section_1 (tree decl, bool force_cold)
> {
>   slot = decl in hash;
>   if (slot)
>     {
>       sec = is_cold ? slot->cold : slot->hot;
>       if (sec)
> 	return sec;
>     }
>   else
>     slot = new hash entry;
> 
>   if (targetm.have_named_sections)
>     {
>       if (DECL_SECTION_NAME (decl))
>         {
>           // The user has setup a section for the function.  Honor it.
>           sec = get_named_section (decl, NULL, 0);
>         }
>       else if (DECL_ONE_ONLY (decl))
>         {
>           // The function must be placed in a comdat section.  Lest we
>           // fail to merge duplicates, the section name is part of the
>           // ABI of the function.  Don't do hot/cold splitting or other
>           // sorts of renames.
> 	  // ??? Note that this still sets DECL_SECTION_NAME; ideally
> 	  // we'd revise the interface to return a section, but it's
> 	  // not critical.
>           targetm.asm_out.unique_section (decl, false);
>           sec = get_named_section (decl, NULL, 0);
> 	}
>     }
>   if (!sec)
>     {
>       // The hook handles all of the details of hot/cold/startup/exit.
>       // It must *not* set DECL_SECTION_NAME, so that when we return
>       // for the !is_cold section we arrive here and don't get confused
>       // by the cases above.
>       sec = targetm.asm_out.function_section (...);
>     }
> 
>   if (is_cold)
>     slot->cold = sec;
>   else
>     slot->hot = sec;
> 
>   return sec;
> }
> 
> 
> 
> r~
Jan Hubicka Nov. 20, 2010, 9:51 p.m. UTC | #10
> 
> Honestly, adding the function_section hook is an excellent opportunity
> to get rid of the USE_SELECT_SECTION_FOR_FUNCTIONS macro, used only by
> darwin and the MEP port.

I am trying to look into this.  I wonder what darwin is using it for after all?
machopic_select_section seems to just return darwin_text_section for all
FUNCTION_DECLs....

Well, this is all bit rotten.  I will try to prepare more updated patch now so
we can discuss things incrementally.

Honza
Jan Hubicka Nov. 21, 2010, 1:12 a.m. UTC | #11
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
Jack Howarth Nov. 21, 2010, 4:35 p.m. UTC | #12
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
Richard Henderson Nov. 22, 2010, 5:15 p.m. UTC | #13
On 11/20/2010 05:12 PM, Jan Hubicka wrote:
> +       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);

Missing leading "." for both of these.

> + /* 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;
> + }

I really really think this is much clearer if we do

  return text_section;

here, but I guess this could be a subsequent cleanup.

> + extern section *ia64_hpux_function_section (decl, enum node_frequency, startup, exit);

This doesn't need to be declared here.  The only real use is within ia64.c;
the reference within hpux.h can just as well talk about the static function.
I suppose you do have to either conditionally define the function or mark
is as ATTRIBUTE_UNUSED.

> + 	          "__TEXT,__unlikely,regular,pure_instructions", "_ulinkely");

Typo in that last string.

> ! #undef UNLIKELY_EXECUTED_TEXT_SECTION_NAME
> ! #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME ".text"
> ! 
> ! #undef HOT_TEXT_SECTION_NAME
> ! #define HOT_TEXT_SECTION_NAME ".text"

Are these now poison-able?

Otherwise ok.


r~
Jan Hubicka Nov. 23, 2010, 3:15 p.m. UTC | #14
> > + /* 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;
> > + }
> 
> I really really think this is much clearer if we do
> 
>   return text_section;
> 
> here, but I guess this could be a subsequent cleanup.

Yep, it would be, but for that USE_SELECT_SECTION_FOR_FUNCTIONS needs to go.  I will be happy to do
that for next stage1.
> > ! #undef UNLIKELY_EXECUTED_TEXT_SECTION_NAME
> > ! #define UNLIKELY_EXECUTED_TEXT_SECTION_NAME ".text"
> > ! 
> > ! #undef HOT_TEXT_SECTION_NAME
> > ! #define HOT_TEXT_SECTION_NAME ".text"
> 
> Are these now poison-able?
Should be. I will add the poison, re-test and commit.  Thanks!

Honza
H.J. Lu Nov. 23, 2010, 8:09 p.m. UTC | #15
On Sat, Nov 20, 2010 at 5:12 PM, Jan Hubicka <hubicka@ucw.cz> 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
>
>        * 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.

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46628

H.J.
H.J. Lu Nov. 26, 2010, 3:56 p.m. UTC | #16
On Tue, Nov 23, 2010 at 12:09 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Nov 20, 2010 at 5:12 PM, Jan Hubicka <hubicka@ucw.cz> 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
>>
>>        * 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.
>
> This caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46628
>

This also caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46667
Mike Stump April 21, 2011, 10:41 p.m. UTC | #17
On Nov 20, 2010, at 5:12 PM, Jan Hubicka wrote:
> 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.

So, I didn't see the patch that poisoned them in system.h.  That patch should have removed the documentation for HOT_TEXT_SECTION_NAME and UNLIKELY_EXECUTED_TEXT_SECTION_NAME?
diff mbox

Patch

Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 166490)
+++ doc/tm.texi	(working copy)
@@ -7335,6 +7335,8 @@  macro is not defined, nothing is output 
 @end defmac
 
 @deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags}, tree @var{decl})
+
+@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_SECTION (tree @var{decl}, enum node_frequency @var{freq}, bool @var{startup}, bool @var{exit})
 Output assembly directives to switch to section @var{name}.  The section
 should have attributes as specified by @var{flags}, which is a bit mask
 of the @code{SECTION_*} flags defined in @file{output.h}.  If @var{decl}
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 166490)
+++ targhooks.h	(working copy)
@@ -169,7 +169,8 @@  extern int default_label_align_after_bar
 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 166490)
+++ target.def	(working copy)
@@ -281,6 +281,19 @@  DEFHOOK
  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 166490)
+++ cgraph.h	(working copy)
@@ -179,20 +179,6 @@  struct GTY(()) cgraph_clone_info
   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.  */
Index: defaults.h
===================================================================
--- defaults.h	(revision 166490)
+++ defaults.h	(working copy)
@@ -897,14 +897,6 @@  see the files COPYING3 and COPYING.RUNTI
 #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
Index: predict.c
===================================================================
--- predict.c	(revision 166490)
+++ predict.c	(working copy)
@@ -78,7 +78,6 @@  static sreal real_zero, real_one, real_a
 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.
@@ -2185,8 +2184,6 @@  estimate_bb_frequencies (void)
       free_aux_for_edges ();
     }
   compute_function_frequency ();
-  if (flag_reorder_functions)
-    choose_function_section ();
 }
 
 /* Decide whether function is hot, cold or unlikely executed.  */
@@ -2232,35 +2229,6 @@  compute_function_frequency (void)
     }
 }
 
-/* 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)
 {
Index: function.h
===================================================================
--- function.h	(revision 166490)
+++ function.h	(working copy)
@@ -226,11 +226,6 @@  struct GTY(()) function_subsections {
   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
Index: coretypes.h
===================================================================
--- coretypes.h	(revision 166490)
+++ coretypes.h	(working copy)
@@ -121,6 +121,22 @@  enum unwind_info_type
   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 166490)
+++ varasm.c	(working copy)
@@ -368,69 +368,6 @@  create_block_symbol (const char *label, 
   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
@@ -539,49 +476,202 @@  hot_function_section (tree decl)
 }
 #endif
 
+/* Hash table used to cache names of function subsections.  */
+struct GTY(()) named_subsection_entry
+{
+  section *sect;
+  tree section_name;
+  const char *suffix;
+};
+
+static GTY((param_is (struct named_subsection_entry))) htab_t subsection_hash;
+
+/* Returns nonzero if P1 and P2 are equal.  */
+
+static int
+eq_subsections (const void *p1, const void *p2)
+{
+  const struct named_subsection_entry *n1 = (const struct named_subsection_entry *) p1;
+  const struct named_subsection_entry *n2 = (const struct named_subsection_entry *) p2;
+  return n1->section_name == n2->section_name && n1->suffix == n2->suffix;
+}
+
+/* Compute hash value of subsection.  */
+static unsigned int
+hash_subsection (const void *p)
+{
+  const struct named_subsection_entry *n = (const struct named_subsection_entry *)p;
+  return htab_hash_pointer (n->section_name) ^ htab_hash_pointer (n->suffix);
+}
+
+/* Return section for TEXT_SECITON_NAME if DECL or DECL_SECTION_NAME (DECL)
+   is NULL.
+
+   If it is non-NULL, return subsection of DECL_SECTION_NAME (DECL) created
+   by appending NAMED_SECTION_SUFFIX.  */
+
+section *
+named_text_subsection (tree decl,
+		       const char *text_section_name,
+		       const char *named_section_suffix)
+{
+  if (decl && DECL_SECTION_NAME (decl))
+    {
+      tree dsn = DECL_SECTION_NAME (decl);
+      struct named_subsection_entry key, *entry, **slot;
+
+      key.suffix = named_section_suffix;
+      key.section_name = dsn;
+      if (!subsection_hash)
+	subsection_hash =
+	  htab_create_ggc (10, hash_subsection, eq_subsections, NULL);
+      slot =
+	(struct named_subsection_entry **) htab_find_slot (subsection_hash,
+							   &key, INSERT);
+      if (!*slot)
+	{
+	  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));
+	  entry = ggc_alloc_named_subsection_entry ();
+	  entry->section_name = dsn;
+	  entry->suffix = named_section_suffix;
+	  entry->sect = get_named_section (decl, buffer, 0);
+	  *slot = entry;
+	}
+      return (*slot)->sect;
+    }
+  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 named_text_subsection (decl, ".text.startup", "_startup");
+
+  /* Similarly for exit.  */
+  if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+    return named_text_subsection (decl, ".text.exit", "_exit");
+
+  /* Group cold functions together, similarly for hot code.  */
+  switch (freq)
+    {
+      case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+	return named_text_subsection (decl, "text.unlikely", "_unlikely");
+      case NODE_FREQUENCY_HOT:
+	return named_text_subsection (decl, "text.hot", "_hot");
+      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.  */
+   NULL_TREE under some circumstances by dbxout.c at least. 
 
-section *
-function_section (tree decl)
+   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)
 {
-  int reloc = 0;
+  section *section = NULL;
+  enum node_frequency freq = NODE_FREQUENCY_NORMAL;
+  bool startup = false, exit = false;
 
-  if (first_function_block_is_cold)
-    reloc = 1;
+  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)
-    return reloc ? unlikely_text_section ()
-		 : get_named_section (decl, NULL, 0);
+    {
+      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, reloc, DECL_ALIGN (decl));
+    return targetm.asm_out.select_section
+	    (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
+	     DECL_ALIGN (decl));
 #else
-  return reloc ? unlikely_text_section () : hot_function_section (decl);
+  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
+		             && flag_function_sections);
+}
+
+/* Return the section for the current function, take IN_COLD_SECTION_P
+   into account.  */
+
 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 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.  */
@@ -1483,16 +1573,10 @@  assemble_start_function (tree decl, cons
   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;
+	 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;
@@ -5841,15 +5925,6 @@  default_section_type_flags (tree decl, c
     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;
 
@@ -6776,12 +6851,6 @@  switch_to_section (section *new_section)
   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);
Index: output.h
===================================================================
--- output.h	(revision 166490)
+++ output.h	(working copy)
@@ -264,6 +264,10 @@  extern bool default_assemble_integer (rt
    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 *named_text_subsection (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 166490)
+++ config/i386/winnt.c	(working copy)
@@ -414,15 +414,6 @@  i386_pe_section_type_flags (tree decl, c
     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;
Index: config/darwin-protos.h
===================================================================
--- config/darwin-protos.h	(revision 166490)
+++ config/darwin-protos.h	(working copy)
@@ -57,6 +57,7 @@  extern section *machopic_select_section 
 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 166490)
+++ config/microblaze/microblaze.h	(working copy)
@@ -880,10 +880,6 @@  do {									 \
 #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.  */
Index: config/ia64/hpux.h
===================================================================
--- config/ia64/hpux.h	(revision 166490)
+++ config/ia64/hpux.h	(working copy)
@@ -221,8 +221,4 @@  do {								\
    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"
+#define TARGET_ASM_FUNCTION_SECTOIN NULL
Index: config/darwin.c
===================================================================
--- config/darwin.c	(revision 166490)
+++ config/darwin.c	(working copy)
@@ -1233,12 +1233,22 @@  machopic_select_section (tree decl,
 	       && DECL_WEAK (decl)
 	       && !lookup_attribute ("weak_import",
 				     DECL_ATTRIBUTES (decl)));
-  section *base_section;
+  section *base_section = NULL;
 
   switch (categorize_decl_for_section (decl, reloc))
     {
     case SECCAT_TEXT:
-      base_section = darwin_text_section (reloc, weak);
+      {
+	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:
@@ -2362,4 +2372,38 @@  darwin_enter_string_into_cfstring_table 
     }
 }
 
+/* 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 named_text_subsection
+	     (decl, "__TEXT,__startup,regular,pure_instructions", "_startup");
+
+  /* Similarly for exit.  */
+  if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
+    return named_text_subsection (decl,
+				  "__TEXT,__exit,regular,pure_instructions",
+				  "_exit");
+
+  /* Group cold functions together, similarly for hot code.  */
+  switch (freq)
+    {
+      case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+	return named_text_subsection
+		 (decl,
+	          "__TEXT,__unlikely,regular,pure_instructions", "_ulinkely");
+      case NODE_FREQUENCY_HOT:
+	return named_text_subsection
+		 (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
+      default:
+	return NULL;
+    }
+}
+
 #include "gt-darwin.h"
Index: config/darwin.h
===================================================================
--- config/darwin.h	(revision 166490)
+++ config/darwin.h	(working copy)
@@ -710,11 +710,6 @@  int darwin_label_is_anonymous_local_objc
 /* 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 {
@@ -729,6 +724,8 @@  extern GTY(()) section * darwin_sections
 #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