tree.h (DECL_HAS_IMPLICIT_SECTION_NAME_P): New macro.

* 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.

From-SVN: r167085
This commit is contained in:
Jan Hubicka 2010-11-23 17:06:37 +01:00 committed by Jan Hubicka
parent 7f814c0bb0
commit f16d3f392e
23 changed files with 362 additions and 209 deletions

View 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).

View 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. */

View File

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

View 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);

View 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"

View 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

View 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;

View 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

View 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);
/* 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"

View 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. */

View 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*)

View 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;

View 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

View 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

View 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

View 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

View 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. */

View 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)
{

View 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

View 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

View 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[];

View 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);

View 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,6 +479,133 @@ 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.
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
@ -547,41 +614,41 @@ hot_function_section (tree decl)
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
/* 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);