This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Hot and cold attributes


Hi,
since the patch on hot and cold attributes didn't generated any negative
feedback and some people (also off list) told me they are interested to
use them, I would like to propose the following patch for approval.

I've re-bootstrapped/regtested it on i686-linux, OK?

	* 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.
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 122618)
+++ gcc/doc/extend.texi	(working copy)
@@ -1578,10 +1578,11 @@ attributes are currently defined for fun
 @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{feo
 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
Index: gcc/errors.h
===================================================================
--- gcc/errors.h	(revision 122618)
+++ gcc/errors.h	(working copy)
@@ -34,10 +34,10 @@ Software Foundation, 51 Franklin Street,
    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;
Index: gcc/predict.c
===================================================================
--- gcc/predict.c	(revision 122618)
+++ gcc/predict.c	(working copy)
@@ -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_bloc
 {
   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)
     {
Index: gcc/function.h
===================================================================
--- gcc/function.h	(revision 122618)
+++ gcc/function.h	(working copy)
@@ -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
 };
 
Index: gcc/predict.def
===================================================================
--- gcc/predict.def	(revision 122618)
+++ gcc/predict.def	(working copy)
@@ -73,6 +73,10 @@ DEF_PREDICTOR (PRED_CONTINUE, "continue"
 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)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 122618)
+++ gcc/c-common.c	(working copy)
@@ -511,6 +511,8 @@ static tree handle_packed_attribute (tre
 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_att
 			      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, t
   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.  */
 
Index: include/ansidecl.h
===================================================================
--- include/ansidecl.h	(revision 122618)
+++ include/ansidecl.h	(working copy)
@@ -367,6 +367,22 @@ So instead we use the macro below and te
 # 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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]