errors.h (warning, [...]): Mark as cold.
* errors.h (warning, error, fatal, internal_error): Mark as cold. * predict.c (maybe_hot_bb): Cold functions are never hot; hot functions are hot. (probably_cold_bb_p): Cold functions are cold. (probably_never_executed_bb_p): Cold functions are cold. (tree_bb_level_predictions): Predict calls to cold functions as not taken. (compute_function_frequency): Check hot/cold attributes. * function.h (function_frequency): Update comments. * predict.def (PRED_COLD_FUNCTION): Predict cold function. * c-common.c (handle_hot_attribute, handle_cold_attribute): New. (c_common_att): Add cold and hot. * doc/extend.texi (hot,cold attributes): Document. * ansidecl.h (ATTRIBUTE_COLD, ATTRIBUTE_HOT): New. From-SVN: r122632
This commit is contained in:
parent
20f326d710
commit
52bf96d2f2
9 changed files with 169 additions and 11 deletions
|
@ -1,3 +1,20 @@
|
|||
2007-03-06 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* errors.h (warning, error, fatal, internal_error): Mark as cold.
|
||||
* predict.c (maybe_hot_bb): Cold functions are never hot; hot functions
|
||||
are hot.
|
||||
(probably_cold_bb_p): Cold functions are cold.
|
||||
(probably_never_executed_bb_p): Cold functions are cold.
|
||||
(tree_bb_level_predictions): Predict calls to cold functions as not
|
||||
taken.
|
||||
(compute_function_frequency): Check hot/cold attributes.
|
||||
* function.h (function_frequency): Update comments.
|
||||
* predict.def (PRED_COLD_FUNCTION): Predict cold function.
|
||||
* c-common.c (handle_hot_attribute, handle_cold_attribute): New.
|
||||
(c_common_att): Add cold and hot.
|
||||
|
||||
* doc/extend.texi (hot,cold attributes): Document.
|
||||
|
||||
2007-03-06 Andrew Haley <aph@redhat.com>
|
||||
|
||||
* function.c (expand_function_end): Move blockage to just after we
|
||||
|
|
|
@ -511,6 +511,8 @@ static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
|
|||
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
|
||||
static tree handle_always_inline_attribute (tree *, tree, tree, int,
|
||||
bool *);
|
||||
|
@ -648,6 +650,10 @@ const struct attribute_spec c_common_attribute_table[] =
|
|||
handle_warn_unused_result_attribute },
|
||||
{ "sentinel", 0, 1, false, true, true,
|
||||
handle_sentinel_attribute },
|
||||
{ "cold", 0, 0, true, false, false,
|
||||
handle_cold_attribute },
|
||||
{ "hot", 0, 0, true, false, false,
|
||||
handle_hot_attribute },
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
|
@ -4432,6 +4438,59 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "hot" and attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
{
|
||||
if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
|
||||
name, "cold");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
/* Do nothing else, just set the attribute. We'll get at
|
||||
it later with lookup_attribute. */
|
||||
}
|
||||
else
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
/* Handle a "cold" and attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||
{
|
||||
if (TREE_CODE (*node) == FUNCTION_DECL)
|
||||
{
|
||||
if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
|
||||
name, "hot");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
/* Do nothing else, just set the attribute. We'll get at
|
||||
it later with lookup_attribute. */
|
||||
}
|
||||
else
|
||||
{
|
||||
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle a "noinline" attribute; arguments as in
|
||||
struct attribute_spec.handler. */
|
||||
|
||||
|
|
|
@ -1578,10 +1578,11 @@ attributes are currently defined for functions on all targets:
|
|||
@code{section}, @code{constructor}, @code{destructor}, @code{used},
|
||||
@code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
|
||||
@code{alias}, @code{warn_unused_result}, @code{nonnull},
|
||||
@code{gnu_inline} and @code{externally_visible}. Several other
|
||||
attributes are defined for functions on particular target systems. Other
|
||||
attributes, including @code{section} are supported for variables declarations
|
||||
(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
|
||||
@code{gnu_inline} and @code{externally_visible}, @code{hot}, @code{cold}.
|
||||
Several other attributes are defined for functions on particular target
|
||||
systems. Other attributes, including @code{section} are supported for
|
||||
variables declarations (@pxref{Variable Attributes}) and for types (@pxref{Type
|
||||
Attributes}).
|
||||
|
||||
You may also specify attributes with @samp{__} preceding and following
|
||||
each keyword. This allows you to use them in header files without
|
||||
|
@ -2242,6 +2243,35 @@ two consecutive calls (such as @code{feof} in a multithreading environment).
|
|||
The attribute @code{pure} is not implemented in GCC versions earlier
|
||||
than 2.96.
|
||||
|
||||
@item hot
|
||||
@cindex @code{hot} function attribute
|
||||
The @code{hot} attribute is used to inform the compiler that a function is a
|
||||
hot spot of the compiled program. The function is optimized more aggressively
|
||||
and on many target it is placed into special subsection of the text section so
|
||||
all hot functions appears close together improving locality.
|
||||
|
||||
When profile feedback is available, via @option{-fprofile-use}, hot functions
|
||||
are automatically detected and this attribute is ignored.
|
||||
|
||||
The @code{hot} attribute is not implemented in GCC versions earlier than 4.3.
|
||||
|
||||
@item cold
|
||||
@cindex @code{cold} function attribute
|
||||
The @code{cold} attribute is used to inform the compiler that a function is
|
||||
unlikely executed. The function is optimized for size rather than speed and on
|
||||
many targets it is placed into special subsection of the text section so all
|
||||
cold functions appears close together improving code locality of non-cold parts
|
||||
of program. The paths leading to call of cold functions within code are marked
|
||||
as unlikely by the branch prediction mechanizm. It is thus useful to mark
|
||||
functions used to handle unlikely conditions, such as @code{perror}, as cold to
|
||||
improve optimization of hot functions that do call marked functions in rare
|
||||
occasions.
|
||||
|
||||
When profile feedback is available, via @option{-fprofile-use}, hot functions
|
||||
are automatically detected and this attribute is ignored.
|
||||
|
||||
The @code{hot} attribute is not implemented in GCC versions earlier than 4.3.
|
||||
|
||||
@item regparm (@var{number})
|
||||
@cindex @code{regparm} attribute
|
||||
@cindex functions that are passed arguments in registers on the 386
|
||||
|
|
|
@ -34,10 +34,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||
version of warning(). For those, you'd pass an OPT_W* value from
|
||||
options.h, but in generator programs it has no effect, so it's OK
|
||||
to just pass zero for calls from generator-only files. */
|
||||
extern void warning (int, const char *, ...) ATTRIBUTE_PRINTF_2;
|
||||
extern void error (const char *, ...) ATTRIBUTE_PRINTF_1;
|
||||
extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1;
|
||||
extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1;
|
||||
extern void warning (int, const char *, ...) ATTRIBUTE_PRINTF_2 ATTRIBUTE_COLD;
|
||||
extern void error (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||
extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||
extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||
extern const char *trim_filename (const char *);
|
||||
|
||||
extern int have_error;
|
||||
|
|
|
@ -168,12 +168,12 @@ DEF_VEC_ALLOC_P(temp_slot_p,gc);
|
|||
|
||||
enum function_frequency {
|
||||
/* This function most likely won't be executed at all.
|
||||
(set only when profile feedback is available). */
|
||||
(set only when profile feedback is available or via function attribute). */
|
||||
FUNCTION_FREQUENCY_UNLIKELY_EXECUTED,
|
||||
/* The default value. */
|
||||
FUNCTION_FREQUENCY_NORMAL,
|
||||
/* Optimize this function hard
|
||||
(set only when profile feedback is available). */
|
||||
(set only when profile feedback is available or via function attribute). */
|
||||
FUNCTION_FREQUENCY_HOT
|
||||
};
|
||||
|
||||
|
|
|
@ -117,6 +117,13 @@ maybe_hot_bb_p (basic_block bb)
|
|||
&& (bb->count
|
||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
return false;
|
||||
if (!profile_info || !flag_branch_probabilities)
|
||||
{
|
||||
if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
|
||||
return false;
|
||||
if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
|
||||
return true;
|
||||
}
|
||||
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -131,6 +138,9 @@ probably_cold_bb_p (basic_block bb)
|
|||
&& (bb->count
|
||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||
return true;
|
||||
if ((!profile_info || !flag_branch_probabilities)
|
||||
&& cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
|
||||
return true;
|
||||
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||
return true;
|
||||
return false;
|
||||
|
@ -142,6 +152,9 @@ probably_never_executed_bb_p (basic_block bb)
|
|||
{
|
||||
if (profile_info && flag_branch_probabilities)
|
||||
return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
|
||||
if ((!profile_info || !flag_branch_probabilities)
|
||||
&& cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1234,6 +1247,7 @@ tree_bb_level_predictions (void)
|
|||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
tree stmt = bsi_stmt (bsi);
|
||||
tree decl;
|
||||
switch (TREE_CODE (stmt))
|
||||
{
|
||||
case GIMPLE_MODIFY_STMT:
|
||||
|
@ -1248,6 +1262,12 @@ call_expr:;
|
|||
if (call_expr_flags (stmt) & ECF_NORETURN)
|
||||
predict_paths_leading_to (bb, heads, PRED_NORETURN,
|
||||
NOT_TAKEN);
|
||||
decl = get_callee_fndecl (stmt);
|
||||
if (decl
|
||||
&& lookup_attribute ("cold",
|
||||
DECL_ATTRIBUTES (decl)))
|
||||
predict_paths_leading_to (bb, heads, PRED_COLD_FUNCTION,
|
||||
NOT_TAKEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1785,7 +1805,15 @@ compute_function_frequency (void)
|
|||
basic_block bb;
|
||||
|
||||
if (!profile_info || !flag_branch_probabilities)
|
||||
return;
|
||||
{
|
||||
if (lookup_attribute ("cold", DECL_ATTRIBUTES (current_function_decl))
|
||||
!= NULL)
|
||||
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
|
||||
else if (lookup_attribute ("hot", DECL_ATTRIBUTES (current_function_decl))
|
||||
!= NULL)
|
||||
cfun->function_frequency = FUNCTION_FREQUENCY_HOT;
|
||||
return;
|
||||
}
|
||||
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
|
|
|
@ -73,6 +73,10 @@ DEF_PREDICTOR (PRED_CONTINUE, "continue", HITRATE (56), 0)
|
|||
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
|
||||
PRED_FLAG_FIRST_MATCH)
|
||||
|
||||
/* Branch to basic block containing call marked by cold function attribute. */
|
||||
DEF_PREDICTOR (PRED_COLD_FUNCTION, "cold function call", HITRATE (99),
|
||||
PRED_FLAG_FIRST_MATCH)
|
||||
|
||||
/* Loopback edge is taken. */
|
||||
DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", HITRATE (86),
|
||||
PRED_FLAG_FIRST_MATCH)
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2007-03-06 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* ansidecl.h (ATTRIBUTE_COLD, ATTRIBUTE_HOT): New.
|
||||
|
||||
2007-02-09 Joseph S. Myers <joseph@codesourcery.com>
|
||||
|
||||
* libiberty.h (pex_write_input): Remove prototype.
|
||||
|
|
|
@ -367,6 +367,22 @@ So instead we use the macro below and test it against specific values. */
|
|||
# define ATTRIBUTE_PACKED __attribute__ ((packed))
|
||||
#endif
|
||||
|
||||
/* Attribute `hot' and `cold' was valid as of gcc 4.3. */
|
||||
#ifndef ATTRIBUTE_COLD
|
||||
# if (GCC_VERSION >= 4003)
|
||||
# define ATTRIBUTE_COLD __attribute__ ((__cold__))
|
||||
# else
|
||||
# define ATTRIBUTE_COLD
|
||||
# endif /* GNUC >= 4.3 */
|
||||
#endif /* ATTRIBUTE_COLD */
|
||||
#ifndef ATTRIBUTE_HOT
|
||||
# if (GCC_VERSION >= 4003)
|
||||
# define ATTRIBUTE_HOT __attribute__ ((__hot__))
|
||||
# else
|
||||
# define ATTRIBUTE_HOT
|
||||
# endif /* GNUC >= 4.3 */
|
||||
#endif /* ATTRIBUTE_HOT */
|
||||
|
||||
/* We use __extension__ in some places to suppress -pedantic warnings
|
||||
about GCC extensions. This feature didn't work properly before
|
||||
gcc 2.8. */
|
||||
|
|
Loading…
Add table
Reference in a new issue