From patchwork Fri Aug 11 13:18:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Javier Martinez X-Patchwork-Id: 134493 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b824:0:b0:3f2:4152:657d with SMTP id z4csp1088329vqi; Fri, 11 Aug 2023 06:19:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGrcuWpxUJ4S4YRVz014Z6WH8aOoNPKDsm9mVmoUJFaWUmW7H7bG8oIFtye1bq1nTD5MSo4 X-Received: by 2002:aa7:cf0f:0:b0:523:1400:2d7c with SMTP id a15-20020aa7cf0f000000b0052314002d7cmr1575454edy.35.1691759999055; Fri, 11 Aug 2023 06:19:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691759999; cv=none; d=google.com; s=arc-20160816; b=TdKdqdp40G5bJWE8kJV3iBMzLXwPA1ySNGl6eWEmDkNtMg6phrw/CON0g+BCjRP7TY WPz1XVC6lCBLyENwbZF9/EWj4Lx7w6H4r3Klbu1SDFSwqTPP80oHPl4rurK94TcB/Tfd sebC9qxQktHFGsu+PKkmi2HDDyysHwobFLXNsViJuCnNoxfN8+eNOh7vHd+8YlbWMeyK zZZev63p6kB6yocuVR8fG9H4ie9PxuxqiPTv4wc3yvSaNS7rdiZDrO7jP26S4TGqZe4X fd3flxVGDg6EpyGU3CONJq/EzKjHG+0V2NHfOhogm6cbLoSXu/pYMje2fmJ5qNf0wjBr KwwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:cc:to:subject :message-id:date:mime-version:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=Uo5p8K9tqcZb4btomtR5oRrnHSUE+6ZTafSE0rV9n3I=; fh=d5QGVRk2N5a5/4r89dmOt0RH0wgWbIxx7/c9RbuhBI0=; b=IFl2TWd1ADDWWkSrmBf2K+Vxz4A6cNsd/a+HOckUhLNq8JtjU+AjNOtVn4SoNAheFq MBWQQFaOOrtVeX6vBz9odNNvHH7L0hACd5D8JRkqNrQ3lUC5XZTE6dmkmCm9gNf1+NCB wVgH0CI/ifIVoBbf0qcK2foMEXW4KK2/P3LXVcZE3blDB47fDKimLCj3eHvtnMTaUHOB B4xU1zRZnqLu+OQduEzpkikOcMd7EkZRl3SpqZTUNe3fBPriIrLvZ8dW9lBeh7tyKAcM vtJWeEL4AlMEDnlSIvPCxBho1EUs8JYWCaHNiyqEkfKN8ggWclUriCjMTnYA8g4gS27O hn1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="Kq/1UtzQ"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id n5-20020a056402060500b005231fc89319si3497538edv.8.2023.08.11.06.19.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Aug 2023 06:19:59 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="Kq/1UtzQ"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 31D41385C6E5 for ; Fri, 11 Aug 2023 13:19:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 31D41385C6E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1691759975; bh=Uo5p8K9tqcZb4btomtR5oRrnHSUE+6ZTafSE0rV9n3I=; h=Date:Subject:To:Cc:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=Kq/1UtzQbm5sGuxjtd9vmBTqQKJfiPid7stKq1e3GWPQFqPvfs4X/o05OATxtwWwa Kntfh3AFykcFd/wBACfBYI8T/py/Tq+2bjUoIZB7YSRuO+H2OD7dh3oPoBYgSLcCUc BJkTOtcj6lsd8KMlTybxbbeyxJJMvw5E/5s3XRpg= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-lj1-x241.google.com (mail-lj1-x241.google.com [IPv6:2a00:1450:4864:20::241]) by sourceware.org (Postfix) with ESMTPS id CBA22385771C for ; Fri, 11 Aug 2023 13:18:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CBA22385771C Received: by mail-lj1-x241.google.com with SMTP id 38308e7fff4ca-2b9e6cc93d8so31987301fa.0 for ; Fri, 11 Aug 2023 06:18:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691759928; x=1692364728; h=cc:to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Lql8indhwqDgaUXoBHft79fpHacBpnj5hP5OondHR0w=; b=gtcPOYcFv393iH3FlGzF4vl5q1zt/hGo2v33KbXfcPVsvZ4UOxt9tw3WrDaOWahtlm OqpyH2KAbFYW/cHTVAu0e2BMsj68XIeV9a22wJiC8sjavuy0HbUUzvmsi8q5R/afEE60 j42MeRlwknZd9p/2ZaclwH9P4G7DJSR1/zUy5TOr4LahH7hLbNIrDtVTD+KZ8R93yyP5 NHuSgExxCbYoh8Pc2y+gnmLImmiFkJjV3T7WbUhwjni8/B4nw+04d1M6Fm9DmShBSNlv geTUrQEZVsx3b/2uAS3I72Mf5BOt/bt6gFHoeWZhhrqvP9ujOxeCF8GH+uVv/OSo9yQv MsBg== X-Gm-Message-State: AOJu0YxtefAHRzFbZWcgpge6l9+2NOfthBSZuyhWucYyu6dcXICavn0Y PaLYZB6ibwGkWEmqlRTYU+c35uBX2WNa9wb2i0+iOdupnCkUBP1dTCc= X-Received: by 2002:a2e:9955:0:b0:2b9:ea17:5590 with SMTP id r21-20020a2e9955000000b002b9ea175590mr1494995ljj.16.1691759927984; Fri, 11 Aug 2023 06:18:47 -0700 (PDT) MIME-Version: 1.0 Date: Fri, 11 Aug 2023 15:18:36 +0200 Message-ID: Subject: [PATCH v3] c++: extend cold, hot attributes to classes To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com X-Spam-Status: No, score=-8.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Javier Martinez via Gcc-patches From: Javier Martinez Reply-To: Javier Martinez Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1773938933135905364 X-GMAIL-MSGID: 1773938933135905364 Hi Jason, Regarding the initialization example - no, the set of classes that we consider cold is more loosely defined. On Thu, Aug 10, 2023 at 11:01 PM Jason Merrill wrote: > Yes, but that's because the implicit op== isn't declared lazily like > some other special member functions (CLASSTYPE_LAZY_*/lazily_declare_fn) > which can happen after the class is complete. I see, thanks. I have fixed this now by injecting it directly from lazily_declare_fn, works well. Doing it from grokclassfn instead seems to be a nuisance because the explicit method attribute might be processed after the class-propagated attribute is injected, which is the wrong way around for the desired precedence. > I think it would work to check for (flags & (ATTR_FLAG_FUNCTION_NEXT | > ATTR_FLAG_DECL_NEXT)) and return without warning in that case. You'd > still set *no_add_attr. Correct, done. I have added the patch as an attachment, if it garbles it then I will use git-send-email next time. From 684ee3b19463fe7f447fbaa96a7b44522f1ce594 Mon Sep 17 00:00:00 2001 From: Javier Martinez Date: Thu, 10 Aug 2023 17:08:27 +0200 Subject: [PATCH v3] c++: extend cold, hot attributes to classes 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. (finish_struct): 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 | 48 +++++++++++++++++++++++-- gcc/cp/class.cc | 29 +++++++++++++++ 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, 135 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..bfd2ff194b5 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,28 @@ 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 ()) + { + /* 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 +1153,28 @@ 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 ()) + { + /* 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..56573d01ec1 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_poverlapping_p (tree); +static void propagate_class_warmth_attribute (tree); /* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */ @@ -7733,6 +7734,30 @@ unreverse_member_declarations (tree t) } } +/* 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) { @@ -7866,6 +7891,10 @@ finish_struct (tree t, tree attributes) && !LAMBDA_TYPE_P (t)) add_stmt (build_min (TAG_DEFN, t)); + /* This must be done after all lazily declared special member functions + have been injected. */ + propagate_class_warmth_attribute (t); + return t; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d051ee85f70..4931a45607e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7033,6 +7033,7 @@ extern int parm_index (tree); 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); diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index b402befba6d..b7c43e10a9d 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -1604,6 +1604,43 @@ cp_check_const_attributes (tree attributes) } } +/* 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) + decl_attributes (&fn, + tree_cons (get_identifier ("cold"), NULL, NULL), 0); + } + else if (has_hot_attr) + { + if (lookup_attribute ("cold", DECL_ATTRIBUTES (fn)) == NULL) + decl_attributes (&fn, + tree_cons (get_identifier ("hot"), NULL, NULL), 0); + } + } +} + /* Return the last pushed declaration for the symbol DECL or NULL when no such declaration exists. */ diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 4ba00175048..741d1049725 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -3592,6 +3592,12 @@ lazily_declare_fn (special_function_kind sfk, tree type) /* 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 finish_struct, + but we must also inject them for deferred lazily_declared functions. */ + + maybe_propagate_warmth_attributes (fn, type); + return fn; } diff --git a/gcc/testsuite/g++.dg/ext/attr-hotness.C b/gcc/testsuite/g++.dg/ext/attr-hotness.C new file mode 100644 index 00000000000..f9a6930304d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/attr-hotness.C @@ -0,0 +1,16 @@ +/* { 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" } } */ + -- 2.34.1