summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog42
-rw-r--r--gcc/cgraph.h14
-rw-r--r--gcc/config.in4
-rw-r--r--gcc/config/darwin-protos.h1
-rw-r--r--gcc/config/darwin.c48
-rw-r--r--gcc/config/darwin.h7
-rw-r--r--gcc/config/i386/winnt.c9
-rw-r--r--gcc/config/ia64/hpux.h6
-rw-r--r--gcc/config/ia64/ia64.c13
-rw-r--r--gcc/config/microblaze/microblaze.h4
-rw-r--r--gcc/configure.ac22
-rw-r--r--gcc/coretypes.h16
-rw-r--r--gcc/defaults.h8
-rw-r--r--gcc/doc/tm.texi10
-rw-r--r--gcc/doc/tm.texi.in10
-rw-r--r--gcc/function.h5
-rw-r--r--gcc/output.h4
-rw-r--r--gcc/predict.c32
-rw-r--r--gcc/system.h5
-rw-r--r--gcc/target.def13
-rw-r--r--gcc/targhooks.h3
-rw-r--r--gcc/tree.h9
-rw-r--r--gcc/varasm.c276
23 files changed, 357 insertions, 204 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f6f36887fb..67c3dfa0bfe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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).
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 99e4ee3eac6..99d549c328a 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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. */
diff --git a/gcc/config.in b/gcc/config.in
index b6a95b53e19..a31fc59d566 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1142,6 +1142,10 @@
#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
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index e70de1bee80..08cacc14234 100644
--- a/gcc/config/darwin-protos.h
+++ b/gcc/config/darwin-protos.h
@@ -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);
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 79b42725f48..e8da4f1e699 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -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"
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index b93f5884ac5..854cb95b407 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -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
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index b8d2979c465..b8d6d69f559 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -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;
diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h
index b422441d343..38a005b0626 100644
--- a/gcc/config/ia64/hpux.h
+++ b/gcc/config/ia64/hpux.h
@@ -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
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 06258cb9136..a007743e2e5 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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);
/* 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"
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 63fd4f6aaf8..2fb438de30f 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -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. */
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 0eb2d8bddee..8d6d1649fa4 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -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*)
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 3c6368419e4..20932b8d9f3 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -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;
diff --git a/gcc/defaults.h b/gcc/defaults.h
index cfbc04d6c92..fb4a8284422 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index fd3f426e106..b58ee7b3117 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index ea4c8430a19..f230307cdad 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -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
diff --git a/gcc/function.h b/gcc/function.h
index 93a9b82601b..fcfa825e0a9 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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
diff --git a/gcc/output.h b/gcc/output.h
index 07372a388a1..928aa1f580f 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -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. */
diff --git a/gcc/predict.c b/gcc/predict.c
index 5fcfc1ea432..cb4edcd185f 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -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)
{
diff --git a/gcc/system.h b/gcc/system.h
index 73e513933f5..4de117ec35f 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -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
diff --git a/gcc/target.def b/gcc/target.def
index 199b58cfc13..22d5660b13d 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -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
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 71b612fa0a8..aff1b2745ed 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -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[];
diff --git a/gcc/tree.h b/gcc/tree.h
index 90170e78d07..8bc52ec87e2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 6171e30799a..fc996f1f8cd 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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);