{ "alloc_size", 1, 2, false, true, true, false,
handle_alloc_size_attribute,
attr_alloc_exclusions },
- { "cold", 0, 0, true, false, false, false,
+ { "cold", 0, 0, false, false, false, false,
handle_cold_attribute,
attr_cold_hot_exclusions },
- { "hot", 0, 0, true, false, false, false,
+ { "hot", 0, 0, false, false, false, false,
handle_hot_attribute,
attr_cold_hot_exclusions },
{ "no_address_safety_analysis",
{
/* Attribute hot processing is done later with lookup_attribute. */
}
+ else if ((TREE_CODE (*node) == RECORD_TYPE
+ || TREE_CODE (*node) == UNION_TYPE)
+ && c_dialect_cxx ()
+ && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ {
+ /* Check conflict here as decl_attributes will otherwise only catch
+ it late at the function when the attribute is used on a class. */
+ tree cold_attr = lookup_attribute ("cold", TYPE_ATTRIBUTES (*node));
+ if (cold_attr)
+ {
+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+ "conflicts with attribute %qs", name, "cold");
+ *no_add_attrs = true;
+ }
+ }
+ else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_DECL_NEXT))
+ {
+ /* Avoid applying the attribute to a function return type when
+ used as: void __attribute ((hot)) foo (void). It will be
+ passed to the function. */
+ *no_add_attrs = true;
+ }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
{
/* Attribute cold processing is done later with lookup_attribute. */
}
+ else if ((TREE_CODE (*node) == RECORD_TYPE
+ || TREE_CODE (*node) == UNION_TYPE)
+ && c_dialect_cxx ()
+ && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ {
+ /* Check conflict here as decl_attributes will otherwise only catch
+ it late at the function when the attribute is used on a class. */
+ tree hot_attr = lookup_attribute ("hot", TYPE_ATTRIBUTES (*node));
+ if (hot_attr)
+ {
+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+ "conflicts with attribute %qs", name, "hot");
+ *no_add_attrs = true;
+ }
+ }
+ else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_DECL_NEXT))
+ {
+ /* Avoid applying the attribute to a function return type when
+ used as: void __attribute ((cold)) foo (void). It will be
+ passed to the function. */
+ *no_add_attrs = true;
+ }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
static bool type_maybe_constexpr_default_constructor (tree);
static bool type_maybe_constexpr_destructor (tree);
static bool field_poverlapping_p (tree);
+static void propagate_class_warmth_attribute (tree);
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
allocating an array of this type. */
LANG_TYPE_CLASS_CHECK (t)->vec_new_uses_cookie
= type_requires_array_cookie (t);
+
+ /* Classes marked hot or cold propagate the attribute to all members. We
+ may do this now that methods are declared. This does miss some lazily
+ declared special member functions (CLASSTYPE_LAZY_*), which are handled
+ in lazily_declare_fn later on. */
+ propagate_class_warmth_attribute (t);
}
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
}
}
+/* Classes, structs or unions T marked with hotness attributes propagate
+ the attribute to all methods. */
+
+void
+propagate_class_warmth_attribute (tree t)
+{
+ if (t == NULL_TREE
+ || !(TREE_CODE (t) == RECORD_TYPE
+ || TREE_CODE (t) == UNION_TYPE))
+ return;
+
+ tree class_has_cold_attr
+ = lookup_attribute ("cold", TYPE_ATTRIBUTES (t));
+ tree class_has_hot_attr
+ = lookup_attribute ("hot", TYPE_ATTRIBUTES (t));
+
+ if (class_has_cold_attr || class_has_hot_attr)
+ for (tree f = TYPE_FIELDS (t); f; f = DECL_CHAIN (f))
+ if (TREE_CODE (f) == FUNCTION_DECL)
+ maybe_propagate_warmth_attributes (f, t);
+}
+
tree
finish_struct (tree t, tree attributes)
{
extern tree vtv_start_verification_constructor_init_function (void);
extern tree vtv_finish_verification_constructor_init_function (tree);
extern void cp_check_const_attributes (tree);
+extern void maybe_propagate_warmth_attributes (tree, tree);
/* in error.cc */
extern const char *type_as_string (tree, int);
}
}
+/* Copies hot or cold attributes to a function FN if present on the
+ encapsulating class, struct, or union TYPE. */
+
+void
+maybe_propagate_warmth_attributes (tree fn, tree type)
+{
+ if (fn == NULL_TREE || type == NULL_TREE
+ || !(TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE))
+ return;
+
+ tree has_cold_attr = lookup_attribute ("cold", TYPE_ATTRIBUTES (type));
+ tree has_hot_attr = lookup_attribute ("hot", TYPE_ATTRIBUTES (type));
+
+ if (has_cold_attr || has_hot_attr)
+ {
+ /* Transparently ignore the new warmth attribute if it
+ conflicts with a present function attribute. Otherwise
+ decl_attribute would still honour the present attribute,
+ but producing an undesired warning in the process. */
+
+ if (has_cold_attr)
+ {
+ if (lookup_attribute ("hot", DECL_ATTRIBUTES (fn)) == NULL)
+ {
+ tree cold_cons
+ = tree_cons (get_identifier ("cold"), NULL, NULL);
+
+ decl_attributes (&fn, cold_cons, 0);
+ }
+ }
+ else if (has_hot_attr)
+ {
+ if (lookup_attribute ("cold", DECL_ATTRIBUTES (fn)) == NULL)
+ {
+ tree hot_cons
+ = tree_cons (get_identifier ("hot"), NULL, NULL);
+
+ decl_attributes (&fn, hot_cons, 0);
+ }
+ }
+ }
+}
+
/* Return the last pushed declaration for the symbol DECL or NULL
when no such declaration exists. */
/* Create appropriate clones. */
clone_cdtor (fn, /*update_methods=*/true);
+ /* Classes, structs or unions TYPE marked with hotness attributes propagate
+ the attribute to all methods. This is typically done in
+ check_bases_and_members, but we must also inject them here for deferred
+ lazily-declared functions. */
+ maybe_propagate_warmth_attributes (fn, type);
+
return fn;
}
to calls of cold functions within code are marked as unlikely by the branch
prediction mechanism. 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.
+of hot functions that do call marked functions in rare occasions. In C++,
+the @code{cold} attribute can be applied to types with the effect of being
+propagated to member functions. See
+@ref{C++ Attributes}.
When profile feedback is available, via @option{-fprofile-use}, cold functions
are automatically detected and this attribute is ignored.
the function is a hot spot of the compiled program. The function is
optimized more aggressively and on many targets it is placed into a special
subsection of the text section so all hot functions appear close together,
-improving locality.
+improving locality. In C++, the @code{hot} attribute can be applied to types
+with the effect of being propagated to member functions. See
+@ref{C++ Attributes}.
When profile feedback is available, via @option{-fprofile-use}, hot functions
are automatically detected and this attribute is ignored.
This attribute is also accepted in C, but it is unnecessary because C
does not have constructors or destructors.
+@cindex @code{cold} type attribute
+@item cold
+
+In addition to functions and labels, GNU C++ allows the @code{cold}
+attribute to be used on C++ classes, structs, or unions. Applying
+the @code{cold} attribute on a type has the effect of treating every
+member function of the type, including implicit special member
+functions, as cold. If a member function is marked with the
+@code{hot} function attribute, the @code{hot} attribute takes
+precedence and the @code{cold} attribute is not propagated.
+
+For the effects of the @code{cold} attribute on functions, see
+@ref{Common Function Attributes}.
+
+@cindex @code{hot} type attribute
+@item hot
+
+In addition to functions and labels, GNU C++ allows the @code{hot}
+attribute to be used on C++ classes, structs, or unions. Applying
+the @code{hot} attribute on a type has the effect of treating every
+member function of the type, including implicit special member
+functions, as hot. If a member function is marked with the
+@code{cold} function attribute, the @code{cold} attribute takes
+precedence and the @code{hot} attribute is not propagated.
+
+For the effects of the @code{hot} attribute on functions, see
+@ref{Common Function Attributes}.
+
@end table
@node Function Multiversioning
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O0 -Wattributes -fdump-tree-gimple" } */
+
+
+struct __attribute((cold)) A { __attribute((noinline, used)) void foo(void) { } };
+
+struct __attribute((hot)) B { __attribute((noinline, used)) void foo(void) { } };
+
+struct __attribute((hot, cold)) C { __attribute((noinline, used)) void foo(void) { } }; /* { dg-warning "ignoring attribute .cold. because it conflicts with attribute .hot." } */
+
+struct __attribute((cold, hot)) D { __attribute((noinline, used)) void foo(void) { } }; /* { dg-warning "ignoring attribute .hot. because it conflicts with attribute .cold." } */
+
+
+/* { dg-final { scan-tree-dump-times "cold" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "hot" 2 "gimple" } } */
+