Commit 52bf96d2 by Jan Hubicka Committed by Jan Hubicka

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
parent 20f326d7
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 *); ...@@ -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[] = ...@@ -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), ...@@ -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: ...@@ -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). ...@@ -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 ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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:; ...@@ -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) ...@@ -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)
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; 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) ...@@ -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)
......
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. */ ...@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment