Re: [PATCH v4] c++: extend cold, hot attributes to classes

2023-08-22 Thread Jason Merrill via Gcc-patches

On 8/15/23 09:41, Javier Martinez wrote:
On Mon, Aug 14, 2023 at 8:32 PM Jason Merrill > wrote:

 > I think you also want to check for ATTR_FLAG_TYPE_IN_PLACE.
 > [...]
 > > +  propagate_class_warmth_attribute (t);
 > Maybe call this in check_bases_and_members instead?

Yes, that is sensible. Done.


You still need an update to doc/extend.texi for this additional use of 
the attribute.  Sorry I didn't think of that before.



+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+   "conflicts with attribute %qs", name, "cold");

...

+ warning (OPT_Wattributes, "ignoring attribute %qE because it "
+   "conflicts with attribute %qs", name, "hot");


Function arguments continuing on the next line should line up with the '('.


+  tree class_has_cold_attr = lookup_attribute ("cold",
+   TYPE_ATTRIBUTES (t));
+  tree class_has_hot_attr = lookup_attribute ("hot",
+   TYPE_ATTRIBUTES (t));


...so I'd suggest reformatting these lines as:

   tree class_has_cold_attr
 = lookup_attribute ("cold", TYPE_ATTRIBUTES (t));
   tree class_has_hot_attr
 = lookup_attribute ("hot", TYPE_ATTRIBUTES (t));


+   decl_attributes (&fn,
+   tree_cons (get_identifier ("cold"), NULL, NULL), 0);


...and maybe use a local variable for the result of tree_cons.


+  if (has_cold_attr || has_hot_attr)
+{
+
+  /* Transparently ignore the new warmth attribute if it


Unnecessary blank line.

Jason



[PATCH v4] c++: extend cold, hot attributes to classes

2023-08-15 Thread Javier Martinez via Gcc-patches
On Mon, Aug 14, 2023 at 8:32 PM Jason Merrill  wrote:
> I think you also want to check for ATTR_FLAG_TYPE_IN_PLACE.
> [...]
> > +  propagate_class_warmth_attribute (t);
> Maybe call this in check_bases_and_members instead?

Yes, that is sensible. Done.

Thanks,
Javier

Signed-off-by: Javier Martinez 
Signed-off-by: Javier Martinez 

gcc/c-family/ChangeLog:

* c-attribs.cc (handle_hot_attribute): remove warning on RECORD_TYPE
and UNION_TYPE when in c_dialect_xx.
(handle_cold_attribute): Likewise.

gcc/cp/ChangeLog:

* class.cc (propagate_class_warmth_attribute): New function.
(check_bases_and_members): propagate hot and cold attributes
to all FUNCTION_DECL when the record is marked hot or cold.
* cp-tree.h (maybe_propagate_warmth_attributes): New function.
* decl2.cc (maybe_propagate_warmth_attributes): New function.
* method.cc (lazily_declare_fn): propagate hot and cold
attributes to lazily declared functions when the record is
marked hot or cold.

gcc/testsuite/ChangeLog:

* g++.dg/ext/attr-hotness.C: New test.
---
 gcc/c-family/c-attribs.cc   | 50 -
 gcc/cp/class.cc | 31 +++
 gcc/cp/cp-tree.h|  1 +
 gcc/cp/decl2.cc | 37 ++
 gcc/cp/method.cc|  6 +++
 gcc/testsuite/g++.dg/ext/attr-hotness.C | 16 
 6 files changed, 139 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/attr-hotness.C

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index e2792ca6898..25083d597c0 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -452,10 +452,10 @@ const struct attribute_spec c_common_attribute_table[] =
   { "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",
@@ -1110,6 +1110,29 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 {
   /* 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);
@@ -1131,6 +1154,29 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 {
   /* 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);
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 778759237dc..bf0b558967f 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -205,6 +205,7 @@ static tree get_vcall_index (tree, tree);
 static bool type_maybe_constexpr_default_constructor (tree);
 static bool type_maybe_constexpr_destructor (tree);
 static bool field_pov