mirror of git://gcc.gnu.org/git/gcc.git
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
|
@ -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>
|
2007-03-06 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
* function.c (expand_function_end): Move blockage to just after we
|
* 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_nocommon_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_common_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_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_noinline_attribute (tree *, tree, tree, int, bool *);
|
||||||
static tree handle_always_inline_attribute (tree *, tree, tree, int,
|
static tree handle_always_inline_attribute (tree *, tree, tree, int,
|
||||||
bool *);
|
bool *);
|
||||||
|
@ -648,6 +650,10 @@ const struct attribute_spec c_common_attribute_table[] =
|
||||||
handle_warn_unused_result_attribute },
|
handle_warn_unused_result_attribute },
|
||||||
{ "sentinel", 0, 1, false, true, true,
|
{ "sentinel", 0, 1, false, true, true,
|
||||||
handle_sentinel_attribute },
|
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 }
|
{ 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;
|
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
|
/* Handle a "noinline" attribute; arguments as in
|
||||||
struct attribute_spec.handler. */
|
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{section}, @code{constructor}, @code{destructor}, @code{used},
|
||||||
@code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
|
@code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
|
||||||
@code{alias}, @code{warn_unused_result}, @code{nonnull},
|
@code{alias}, @code{warn_unused_result}, @code{nonnull},
|
||||||
@code{gnu_inline} and @code{externally_visible}. Several other
|
@code{gnu_inline} and @code{externally_visible}, @code{hot}, @code{cold}.
|
||||||
attributes are defined for functions on particular target systems. Other
|
Several other attributes are defined for functions on particular target
|
||||||
attributes, including @code{section} are supported for variables declarations
|
systems. Other attributes, including @code{section} are supported for
|
||||||
(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
|
variables declarations (@pxref{Variable Attributes}) and for types (@pxref{Type
|
||||||
|
Attributes}).
|
||||||
|
|
||||||
You may also specify attributes with @samp{__} preceding and following
|
You may also specify attributes with @samp{__} preceding and following
|
||||||
each keyword. This allows you to use them in header files without
|
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
|
The attribute @code{pure} is not implemented in GCC versions earlier
|
||||||
than 2.96.
|
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})
|
@item regparm (@var{number})
|
||||||
@cindex @code{regparm} attribute
|
@cindex @code{regparm} attribute
|
||||||
@cindex functions that are passed arguments in registers on the 386
|
@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
|
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
|
options.h, but in generator programs it has no effect, so it's OK
|
||||||
to just pass zero for calls from generator-only files. */
|
to just pass zero for calls from generator-only files. */
|
||||||
extern void warning (int, const char *, ...) ATTRIBUTE_PRINTF_2;
|
extern void warning (int, const char *, ...) ATTRIBUTE_PRINTF_2 ATTRIBUTE_COLD;
|
||||||
extern void error (const char *, ...) ATTRIBUTE_PRINTF_1;
|
extern void error (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||||
extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1;
|
extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||||
extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1;
|
extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
|
||||||
extern const char *trim_filename (const char *);
|
extern const char *trim_filename (const char *);
|
||||||
|
|
||||||
extern int have_error;
|
extern int have_error;
|
||||||
|
|
|
@ -168,12 +168,12 @@ DEF_VEC_ALLOC_P(temp_slot_p,gc);
|
||||||
|
|
||||||
enum function_frequency {
|
enum function_frequency {
|
||||||
/* This function most likely won't be executed at all.
|
/* 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,
|
FUNCTION_FREQUENCY_UNLIKELY_EXECUTED,
|
||||||
/* The default value. */
|
/* The default value. */
|
||||||
FUNCTION_FREQUENCY_NORMAL,
|
FUNCTION_FREQUENCY_NORMAL,
|
||||||
/* Optimize this function hard
|
/* 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
|
FUNCTION_FREQUENCY_HOT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,13 @@ maybe_hot_bb_p (basic_block bb)
|
||||||
&& (bb->count
|
&& (bb->count
|
||||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||||
return false;
|
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))
|
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -131,6 +138,9 @@ probably_cold_bb_p (basic_block bb)
|
||||||
&& (bb->count
|
&& (bb->count
|
||||||
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
< profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
|
||||||
return true;
|
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))
|
if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -142,6 +152,9 @@ probably_never_executed_bb_p (basic_block bb)
|
||||||
{
|
{
|
||||||
if (profile_info && flag_branch_probabilities)
|
if (profile_info && flag_branch_probabilities)
|
||||||
return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,6 +1247,7 @@ tree_bb_level_predictions (void)
|
||||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||||
{
|
{
|
||||||
tree stmt = bsi_stmt (bsi);
|
tree stmt = bsi_stmt (bsi);
|
||||||
|
tree decl;
|
||||||
switch (TREE_CODE (stmt))
|
switch (TREE_CODE (stmt))
|
||||||
{
|
{
|
||||||
case GIMPLE_MODIFY_STMT:
|
case GIMPLE_MODIFY_STMT:
|
||||||
|
@ -1248,6 +1262,12 @@ call_expr:;
|
||||||
if (call_expr_flags (stmt) & ECF_NORETURN)
|
if (call_expr_flags (stmt) & ECF_NORETURN)
|
||||||
predict_paths_leading_to (bb, heads, PRED_NORETURN,
|
predict_paths_leading_to (bb, heads, PRED_NORETURN,
|
||||||
NOT_TAKEN);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1785,7 +1805,15 @@ compute_function_frequency (void)
|
||||||
basic_block bb;
|
basic_block bb;
|
||||||
|
|
||||||
if (!profile_info || !flag_branch_probabilities)
|
if (!profile_info || !flag_branch_probabilities)
|
||||||
|
{
|
||||||
|
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;
|
return;
|
||||||
|
}
|
||||||
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
|
cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
|
||||||
FOR_EACH_BB (bb)
|
FOR_EACH_BB (bb)
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,6 +73,10 @@ DEF_PREDICTOR (PRED_CONTINUE, "continue", HITRATE (56), 0)
|
||||||
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
|
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
|
||||||
PRED_FLAG_FIRST_MATCH)
|
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. */
|
/* Loopback edge is taken. */
|
||||||
DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", HITRATE (86),
|
DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", HITRATE (86),
|
||||||
PRED_FLAG_FIRST_MATCH)
|
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>
|
2007-02-09 Joseph S. Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* libiberty.h (pex_write_input): Remove prototype.
|
* 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))
|
# define ATTRIBUTE_PACKED __attribute__ ((packed))
|
||||||
#endif
|
#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
|
/* We use __extension__ in some places to suppress -pedantic warnings
|
||||||
about GCC extensions. This feature didn't work properly before
|
about GCC extensions. This feature didn't work properly before
|
||||||
gcc 2.8. */
|
gcc 2.8. */
|
||||||
|
|
Loading…
Reference in New Issue