* tree.h (DECL_HAS_IMPLICIT_SECTION_NAME_P): New macro.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Nov 2010 16:06:37 +0000 (16:06 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Nov 2010 16:06:37 +0000 (16:06 +0000)
(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/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.
* system.h (HOT_TEXT_SECTION_NAME,
UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Poison.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167085 138bc75d-0d04-0410-961f-82ee72b054a4

23 files changed:
gcc/ChangeLog
gcc/cgraph.h
gcc/config.in
gcc/config/darwin-protos.h
gcc/config/darwin.c
gcc/config/darwin.h
gcc/config/i386/winnt.c
gcc/config/ia64/hpux.h
gcc/config/ia64/ia64.c
gcc/config/microblaze/microblaze.h
gcc/configure.ac
gcc/coretypes.h
gcc/defaults.h
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/function.h
gcc/output.h
gcc/predict.c
gcc/system.h
gcc/target.def
gcc/targhooks.h
gcc/tree.h
gcc/varasm.c

index 8f6f368..67c3dfa 100644 (file)
@@ -1,3 +1,45 @@
+2010-11-23  Jan Hubicka  <jh@suse.cz>
+
+       * 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/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.
+       * system.h (HOT_TEXT_SECTION_NAME,
+       UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Poison.
+
 2010-11-23  Iain Sandoe  <iains@gcc.gnu.org>
 
        * config/darwin.h (LINK_COMMAND_SPEC_A): Use %(link_gcc_c_sequence).
index 99e4ee3..99d549c 100644 (file)
@@ -180,20 +180,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 b6a95b5..a31fc59 100644 (file)
 #undef HAVE_LD_DEMANGLE
 #endif
 
+/* Define if your linker supports plugin. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PLUGIN
+#endif
 
 /* Define if your linker supports --eh-frame-hdr option. */
 #undef HAVE_LD_EH_FRAME_HDR
index e70de1b..08cacc1 100644 (file)
@@ -57,6 +57,7 @@ extern section *machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
 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 79b4272..e8da4f1 100644 (file)
@@ -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 (tree str)
     }
 }
 
+/* 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", "_unlikely");
+      case NODE_FREQUENCY_HOT:
+       return get_named_text_section
+                (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
+      default:
+       return NULL;
+    }
+}
+
 #include "gt-darwin.h"
index b93f588..854cb95 100644 (file)
@@ -664,11 +664,6 @@ int darwin_label_is_anonymous_local_objc_name (const char *name);
 /* 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 {
@@ -683,6 +678,8 @@ extern GTY(()) section * darwin_sections[NUM_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
index b8d2979..b8d6d69 100644 (file)
@@ -414,15 +414,6 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc)
     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 b422441..38a005b 100644 (file)
@@ -218,8 +218,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_SECTION ia64_hpux_function_section
index 06258cb..a007743 100644 (file)
@@ -336,6 +336,8 @@ static tree ia64_builtin_decl (unsigned, bool);
 
 static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t);
 static enum machine_mode ia64_get_reg_raw_mode (int regno);
+static section * ia64_hpux_function_section (tree, enum node_frequency,
+                                            bool, bool);
 \f
 /* Table of valid machine attributes.  */
 static const struct attribute_spec ia64_attribute_table[] =
@@ -11022,4 +11024,15 @@ ia64_get_reg_raw_mode (int regno)
   return default_get_reg_raw_mode(regno);
 }
 
+/* Always default to .text section until HP-UX linker is fixed.  */
+
+ATTRIBUTE_UNUSED static 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 63fd4f6..2fb438d 100644 (file)
@@ -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 0eb2d8b..8d6d164 100644 (file)
@@ -3127,6 +3127,28 @@ if test x"$demangler_in_ld" = xyes; then
   AC_MSG_RESULT($gcc_cv_ld_demangle)
 fi
 
+if test x"$linker_plugin_in_ld" = xyes; then
+  AC_MSG_CHECKING(linker support)
+  gcc_cv_ld_plugin=no
+  if test x"$ld_is_gold" = xyes; then
+      gcc_cv_ld_plugin=yes
+  else if test $in_tree_ld = yes; then
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then \
+      gcc_cv_ld_plugin=yes
+    fi
+  elif test x$PLUGIN_LD != x -a x"$gnu_ld" = xyes; then
+    # Check if the GNU linker supports --plugin-opt option
+    if $gcc_cv_ld --help 2>/dev/null | grep no-demangle > /dev/null; then
+      gcc_cv_ld_plugin=yes
+    fi
+  fi
+  if test x"$gcc_cv_ld_plugin" = xyes; then
+    AC_DEFINE(HAVE_LD_PLUGIN, 1,
+[Define if your linker supports plugin.])
+  fi
+  AC_MSG_RESULT($gcc_cv_ld_plugin)
+fi
+
 case "$target" in
   # All TARGET_ABI_OSF targets.
   alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
index 3c63684..20932b8 100644 (file)
@@ -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 cfbc04d..fb4a828 100644 (file)
@@ -897,14 +897,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #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 fd3f426..b58ee7b 100644 (file)
@@ -7328,6 +7328,16 @@ is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which
 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 ea4c843..f230307 100644 (file)
@@ -7303,6 +7303,16 @@ is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which
 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 93a9b82..fcfa825 100644 (file)
@@ -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 07372a3..928aa1f 100644 (file)
@@ -269,6 +269,10 @@ extern bool default_assemble_integer (rtx, unsigned int, int);
    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 5fcfc1e..cb4edcd 100644 (file)
@@ -78,7 +78,6 @@ static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
 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 73e5139..4de117e 100644 (file)
@@ -725,8 +725,9 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
        OPTIMIZATION_OPTIONS CLASS_LIKELY_SPILLED_P                     \
        USING_SJLJ_EXCEPTIONS TARGET_UNWIND_INFO                        \
        LABEL_ALIGN_MAX_SKIP LOOP_ALIGN_MAX_SKIP                        \
-       LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP JUMP_ALIGN_MAX_SKIP \
-       CAN_DEBUG_WITHOUT_FP
+       LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP JUMP_ALIGN_MAX_SKIP          \
+       CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME        \
+       HOT_TEXT_SECTION_NAME
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
index 199b58c..22d5660 100644 (file)
@@ -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 71b612f..aff1b27 100644 (file)
@@ -171,7 +171,8 @@ extern int default_label_align_after_barrier_max_skip (rtx);
 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 90170e7..8bc52ec 100644 (file)
@@ -3107,6 +3107,11 @@ struct GTY(()) tree_parm_decl {
 #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;
@@ -3135,7 +3140,9 @@ struct GTY(()) tree_decl_with_vis {
  unsigned init_priority_p : 1;
  /* Used by C++ only.  Might become a generic decl flag.  */
  unsigned shadowed_for_var_p : 1;
- /* 14 unused bits. */
+ /* 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 6171e30..fc996f1 100644 (file)
@@ -368,69 +368,6 @@ create_block_symbol (const char *label, struct object_block *block,
   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
@@ -462,7 +399,10 @@ resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
       && targetm.have_named_sections
       && (flag_function_or_data_sections
          || DECL_ONE_ONLY (decl)))
-    targetm.asm_out.unique_section (decl, reloc);
+    {
+      targetm.asm_out.unique_section (decl, reloc);
+      DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true;
+    }
 }
 
 #ifdef BSS_SECTION_ASM_OP
@@ -539,49 +479,176 @@ hot_function_section (tree decl)
 }
 #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.  */
+   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 (decl)
+    {
+      struct cgraph_node *node = cgraph_node (decl);
 
-  if (first_function_block_is_cold)
-    reloc = 1;
+      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);
+}
+
+/* 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.  */
@@ -1454,8 +1521,6 @@ assemble_start_function (tree decl, const char *fnname)
   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)
     {
@@ -1513,16 +1578,10 @@ assemble_start_function (tree decl, const char *fnname)
   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;
@@ -5871,15 +5930,6 @@ default_section_type_flags (tree decl, const char *name, int reloc)
     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;
 
@@ -6810,12 +6860,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);