From patchwork Wed Nov 9 19:02:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernhard Reutner-Fischer X-Patchwork-Id: 60292 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6943A3858D38 for ; Wed, 9 Nov 2022 19:04:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6943A3858D38 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668020697; bh=T/Xdqd0+JbL3Dry+fePSG+KWOps41WiWjaiWGTMQoXA=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=GeuGy8d/KVZI6Kv+4Bw9aF9xhCiyDp99wBrYjcjRclmr1V1FCVp7RNsHL8g1x3AsS 35vzwaeMaXmdr8ZtNrnla3fWxKu0FyFhiTkovqapCZ56xbOMGirFr0xWLlkFcbWizR 8I+4e5lL+TOanbU7wPecxfaAlqlMhzZQq9Sa15wE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by sourceware.org (Postfix) with ESMTPS id 09E5C3858D33; Wed, 9 Nov 2022 19:02:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 09E5C3858D33 Received: by mail-ej1-x62d.google.com with SMTP id k2so49464665ejr.2; Wed, 09 Nov 2022 11:02:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=T/Xdqd0+JbL3Dry+fePSG+KWOps41WiWjaiWGTMQoXA=; b=RsRc0E1PBfOT1qazLEnFpZoXoSoxItMlKMGDL0yIWQyoAv6hU4Ymi3FTOgm2Hp0NEE +xUXi86Z25mxz0gbHz3wJ3JFi3IoFmItL+TrsmkR4PTbjCDqgI/qYk5QwvKGZ0xP2jvT MxLPlme4WoUIAxjTiwcI67zeotZ2CQR2tWI/Xuvp0u8jxRJHr1wrKMp69U69jig85pj/ oc2mww9Wx5iWGBO/CsLYUMZzjXRXSB9cdUO6d49/7FNgeqbDVFq5tEoGL/vJ/S1PcBHc 8+m/9dml1svMK+V7IZOGNqMRakj1t36cJhlFr6iGnTrAdeiiQaEPv4U11CbykhY2lwfl +XJg== X-Gm-Message-State: ACrzQf0zUS9PvHhrU7UCox4XNG5cpIUMiD4IkMcgYep0ICB1eD2Eo2+D WKvWUo3gPQh3LwcOKNS6B35Y2L5USW4= X-Google-Smtp-Source: AMsMyM6yRVTH3R8Uru/B5DCTswVOLKIWnFwzjr0/3DE6s8EJX9+pej99Q/GGyER4OqY4QNClo5TKiA== X-Received: by 2002:a17:906:cc47:b0:7ad:d0de:3ce1 with SMTP id mm7-20020a170906cc4700b007add0de3ce1mr50049968ejb.329.1668020559685; Wed, 09 Nov 2022 11:02:39 -0800 (PST) Received: from nbbrfq (80-110-214-113.static.upcbusiness.at. [80.110.214.113]) by smtp.gmail.com with ESMTPSA id d25-20020a170906305900b0073ddb2eff27sm6137441ejd.167.2022.11.09.11.02.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Nov 2022 11:02:37 -0800 (PST) X-Google-Original-From: Bernhard Reutner-Fischer Received: from b by nbbrfq with local (Exim 4.96) (envelope-from ) id 1osqLM-000OzO-21; Wed, 09 Nov 2022 20:02:36 +0100 To: gcc-patches@gcc.gnu.org Cc: Bernhard Reutner-Fischer , Bernhard Reutner-Fischer , gfortran ML Subject: [PATCH 2/2] Fortran: add attribute target_clones Date: Wed, 9 Nov 2022 20:02:25 +0100 Message-Id: <20221109190225.96037-3-aldot@gcc.gnu.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221109190225.96037-1-aldot@gcc.gnu.org> References: <20221109190225.96037-1-aldot@gcc.gnu.org> MIME-Version: 1.0 X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, 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-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: Bernhard Reutner-Fischer via Gcc-patches From: Bernhard Reutner-Fischer Reply-To: Bernhard Reutner-Fischer Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi! Add support for attribute target_clones: !GCC$ ATTRIBUTES target_clones("arch1", "arch3","default") :: mysubroutine Bootstrapped and regtested on x86_64-unknown-linux with --target_board=unix'{-m32,-m64}'. OK for trunk? gcc/fortran/ChangeLog: * decl.cc: Include fold-const.h for size_int. (gfc_match_gcc_attribute_args): New internal helper function. (gfc_match_gcc_attributes): Handle target_clones. * f95-lang.cc (struct attribute_spec): Add target and target_clones entries. * gfortran.h (ext_attr_id_t): Add EXT_ATTR_TARGET_CLONES. (struct symbol_attribute): Add field ext_attr_args. * trans-decl.cc (add_attributes_to_decl): Also add ext_attr_args to the decl's attributes. * gfortran.texi: Document attribute target_clones. gcc/testsuite/ChangeLog: * gfortran.dg/attr_target_clones-1.F90: New test. Cc: gfortran ML --- gcc/fortran/decl.cc | 104 ++++++++++++++++++ gcc/fortran/f95-lang.cc | 4 + gcc/fortran/gfortran.h | 2 + gcc/fortran/gfortran.texi | 31 ++++++ gcc/fortran/trans-decl.cc | 3 + .../gfortran.dg/attr_target_clones-1.F90 | 30 +++++ 6 files changed, 174 insertions(+) create mode 100644 gcc/testsuite/gfortran.dg/attr_target_clones-1.F90 diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index 0f9b2ced4c2..3a619dbdd34 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "options.h" #include "tree.h" +#include "fold-const.h" #include "gfortran.h" #include "stringpool.h" #include "match.h" @@ -11709,6 +11710,96 @@ gfc_match_final_decl (void) return MATCH_YES; } +/* Internal helper to parse attribute argument list. + If REQUIRE_STRING is true, then require a string. + If ALLOW_MULTIPLE is true, allow more than one arg. + If multiple arguments are passed, require braces around them. + Returns a tree_list of arguments or NULL_TREE. */ +static tree +gfc_match_gcc_attribute_args (bool require_string, bool allow_multiple) +{ + tree attr_args = NULL_TREE, attr_arg; + char name[GFC_MAX_SYMBOL_LEN + 1]; + unsigned pos = 0; + gfc_char_t c; + + /* When we get here, we already parsed + !GCC$ ATTRIBUTES ATTRIBUTE_NAME + Now parse the arguments. These could be one of + "single_string_literal" + ( "str_literal_1" , "str_literal_2" ) + */ + + gfc_gobble_whitespace (); + + if (allow_multiple && gfc_match_char ('(') != MATCH_YES) + { + gfc_error ("expected '(' at %C"); + return NULL_TREE; + } + + if (require_string) + { + do { + if (pos) + { + if (!allow_multiple) + { + gfc_error ("surplus argument at %C"); + return NULL_TREE; + } + gfc_next_ascii_char (); /* Consume the comma. */ + } + pos = 0; + gfc_gobble_whitespace (); + unsigned char num_quotes = 0; + do { + c = gfc_next_char_literal (NONSTRING); + if (c == '"') + { + num_quotes++; + continue; /* Skip the quote */ + } + name[pos++] = c; + if (pos >= GFC_MAX_SYMBOL_LEN) + { + gfc_error ("attribute argument truncated at %C"); + return NULL_TREE; + } + } while (num_quotes % 2 && gfc_match_eos () != MATCH_YES); + if (pos < 1) + { + gfc_error ("expected argument at %C"); + return NULL_TREE; + } + if (num_quotes != 2) + { + gfc_error ("invalid string literal at %C"); + return NULL_TREE; + } + name[pos] = '\0'; /* Redundant wrt build_string. */ + tree str = build_string (pos, name); + /* Compare with c-family/c-common.cc: fix_string_type. */ + tree i_type = build_index_type (size_int (pos)); + tree a_type = build_array_type (char_type_node, i_type); + TREE_TYPE (str) = a_type; + TREE_READONLY (str) = 1; + TREE_STATIC (str) = 1; + attr_arg = build_tree_list (NULL_TREE, str); + attr_args = chainon (attr_args, attr_arg); + + gfc_gobble_whitespace (); + } while (gfc_peek_ascii_char () == ','); + } + + if (allow_multiple && gfc_match_char (')') != MATCH_YES) + { + gfc_error ("expected ')' at %C"); + return NULL_TREE; + } + + return attr_args; +} const ext_attr_t ext_attr_list[] = { { "dllimport", EXT_ATTR_DLLIMPORT, "dllimport" }, @@ -11718,6 +11809,7 @@ const ext_attr_t ext_attr_list[] = { { "fastcall", EXT_ATTR_FASTCALL, "fastcall" }, { "no_arg_check", EXT_ATTR_NO_ARG_CHECK, NULL }, { "deprecated", EXT_ATTR_DEPRECATED, NULL }, + { "target_clones",EXT_ATTR_TARGET_CLONES,NULL }, { NULL, EXT_ATTR_LAST, NULL } }; @@ -11743,6 +11835,7 @@ gfc_match_gcc_attributes (void) unsigned id; gfc_symbol *sym; match m; + tree attr_args = NULL_TREE; gfc_clear_attr (&attr); for(;;) @@ -11761,6 +11854,15 @@ gfc_match_gcc_attributes (void) gfc_error ("Unknown attribute in !GCC$ ATTRIBUTES statement at %C"); return MATCH_ERROR; } + else if (id == EXT_ATTR_TARGET_CLONES) + { + attr_args + = gfc_match_gcc_attribute_args(true, true); + if (attr_args != NULL_TREE) + attr.ext_attr_args + = chainon (attr.ext_attr_args, + build_tree_list (get_identifier (name), attr_args)); + } if (!gfc_add_ext_attribute (&attr, (ext_attr_id_t)id, &gfc_current_locus)) return MATCH_ERROR; @@ -11793,6 +11895,8 @@ gfc_match_gcc_attributes (void) return MATCH_ERROR; sym->attr.ext_attr |= attr.ext_attr; + sym->attr.ext_attr_args + = chainon (sym->attr.ext_attr_args, attr.ext_attr_args); if (gfc_match_eos () == MATCH_YES) break; diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc index a6750bea787..7154568aec5 100644 --- a/gcc/fortran/f95-lang.cc +++ b/gcc/fortran/f95-lang.cc @@ -97,6 +97,10 @@ static const struct attribute_spec gfc_attribute_table[] = gfc_handle_omp_declare_target_attribute, NULL }, { "oacc function", 0, -1, true, false, false, false, gfc_handle_omp_declare_target_attribute, NULL }, + { "target", 1, -1, true, false, false, false, + gfc_handle_omp_declare_target_attribute, NULL }, + { "target_clones", 1, -1, true, false, false, false, + gfc_handle_omp_declare_target_attribute, NULL }, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 6bd8800ecf8..ce0cb61e647 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -838,6 +838,7 @@ typedef enum EXT_ATTR_FASTCALL, EXT_ATTR_NO_ARG_CHECK, EXT_ATTR_DEPRECATED, + EXT_ATTR_TARGET_CLONES, EXT_ATTR_LAST, EXT_ATTR_NUM = EXT_ATTR_LAST } ext_attr_id_t; @@ -1009,6 +1010,7 @@ typedef struct /* Attributes set by compiler extensions (!GCC$ ATTRIBUTES). */ unsigned ext_attr:EXT_ATTR_NUM; + tree ext_attr_args; /* The namespace where the attribute has been set. */ struct gfc_namespace *volatile_ns, *asynchronous_ns; diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 4b4ecd528a7..06e4c8c00a1 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3248,6 +3248,37 @@ deprecated procedure, variable or parameter; the warning can be suppressed with @option{-Wno-deprecated-declarations}. @end itemize +@node target_clones (@var{options}) + +Procedures can be annotated with a @code{target_clones} attribute to +instruct the compiler to emit multiple versions of the procedure, each +compiled with different target options in addition to those specified on +the command line. The calling code remains exactly the same. +Please refer to +@ref{Top,,Common Function Attributes,gcc,Using the GNU Compiler Collection (GCC)} +for details about the respective attribute. + +For example, + +@smallexample +module mymod +contains + subroutine sub1 +!GCC$ ATTRIBUTES target_clones("avx", "sse", "default") :: sub1 + ! your code here + end +end module mymod +@end smallexample +or, +@smallexample +module mymod +contains + subroutine sub1 +!GCC$ ATTRIBUTES target_clones("power10","power9","power8","power7","default") :: sub1 + ! your code here will be optimized for several PPC target architectures + end +end module mymod +@end smallexample The attributes are specified using the syntax diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 63515b9072a..24cbd4cda28 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -1447,6 +1447,9 @@ add_attributes_to_decl (symbol_attribute sym_attr, tree list) NULL_TREE); list = chainon (list, attr); } + /* Add attribute args. */ + if (sym_attr.ext_attr_args != NULL_TREE) + list = chainon (list, sym_attr.ext_attr_args); tree clauses = NULL_TREE; diff --git a/gcc/testsuite/gfortran.dg/attr_target_clones-1.F90 b/gcc/testsuite/gfortran.dg/attr_target_clones-1.F90 new file mode 100644 index 00000000000..724e58021fa --- /dev/null +++ b/gcc/testsuite/gfortran.dg/attr_target_clones-1.F90 @@ -0,0 +1,30 @@ +! { dg-require-ifunc "" } +! { dg-options "-O1" } +! { dg-additional-options "-fdump-tree-optimized" } +! It seems arch defines are not defined?! +! See fortran.cpp FIXME: Pandora's Box +! Ok, so enterprise-level bugfix: +! { dg-additional-options "-D__i686__=1" { target { i?86-*-* } } } +! { dg-additional-options "-D__x86_64__=1" { target { x86_64-*-* } } } +! { dg-additional-options "-D__powerpc__=1" { target { powerpc*-*-* } } } +! { dg-skip-if "test not yet implemented for target" { ! {i?86-*-* x86_64-*-* powerpc*-*-*} } } +! Test __attribute__ ((target_clones ("foo", "bar"))) +! +module m + implicit none +contains + subroutine sub1() +#if defined __i686__ || defined __x86_64__ +!GCC$ ATTRIBUTES target_clones("avx", "sse","default") :: sub1 +#elif defined __powerpc__ +!GCC$ ATTRIBUTES target_clones("power10", "power9","default") :: sub1 +#endif + print *, 4321 + end +end module m +! { dg-final { scan-tree-dump-times {(?n)void \* __m_MOD_sub1\.resolver \(\)} 1 "optimized" } } +! { dg-final { scan-tree-dump-times {(?n)void __m_MOD_sub1\.(?:avx|power10) \(\)} 1 "optimized" } } +! { dg-final { scan-tree-dump-times {(?n)void __m_MOD_sub1\.(?:sse|power9) \(\)} 1 "optimized" } } +! { dg-final { scan-tree-dump-times {(?n)void sub1 \(\)} 1 "optimized" } } +!! and a non-assembly hint on the ifunc +! { dg-final { scan-tree-dump-times {Function sub1 \(__m_MOD_sub1\.default,} 1 "optimized" } }