From patchwork Tue Jun 28 17:11:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 55507 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 F14373856DCA for ; Tue, 28 Jun 2022 17:12:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F14373856DCA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1656436340; bh=6Kn9kSjrwfa+UouivFXe7YfaP/ZRM3T+Hv7Kfekar68=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=SIfMA/QYoVdj5uc87SJZWK1tQGNd2zTvEBWaGOpBz6DlBcQD0yMQq0tYYhYlzJVN6 cueeygXawT0BveRVXuZnkifBankyGJsbm8MF0NuU0uSxcsnq9hdLSlAcVcY1xHpz0W Rf5ygVPRhN4+X6fiXzyrmKHw75i1zTUdBiQwNAEk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [IPv6:2001:67c:2050:0:465::102]) by sourceware.org (Postfix) with ESMTPS id F3E6D3856DDD for ; Tue, 28 Jun 2022 17:11:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F3E6D3856DDD Received: from smtp1.mailbox.org (smtp1.mailbox.org [10.196.197.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4LXWNL3KP5z9sVN; Tue, 28 Jun 2022 19:11:46 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Add @simd and @simd_clones attributes to compiler and library Date: Tue, 28 Jun 2022 19:11:44 +0200 Message-Id: <20220628171144.187681-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch adds a `@simd' attribute to the D front-end, which is equivalent to `__attribute__((simd))', and `@simd_clones' is a convenience alias to allow specifying whether the compiler should generated masked or non-masked simd clones. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: * d-attribs.cc (handle_omp_declare_simd_attribute): New function. (d_handle_simd_attribute): New function. (d_langhook_common_attribute_table): Add 'omp declare simd' attribute. (d_langhook_attribute_table): Add simd attribute. libphobos/ChangeLog: * libdruntime/gcc/attributes.d (simd): Define. gcc/testsuite/ChangeLog: * gdc.dg/attr_simd1.d: New test. * gdc.dg/attr_simd2.d: New test. --- gcc/d/d-attribs.cc | 65 ++++++++++++++++++++++++++ gcc/testsuite/gdc.dg/attr_simd1.d | 40 ++++++++++++++++ gcc/testsuite/gdc.dg/attr_simd2.d | 16 +++++++ libphobos/libdruntime/gcc/attributes.d | 40 ++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 gcc/testsuite/gdc.dg/attr_simd1.d create mode 100644 gcc/testsuite/gdc.dg/attr_simd2.d diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc index 1dd806f7144..04f7f1686a2 100644 --- a/gcc/d/d-attribs.cc +++ b/gcc/d/d-attribs.cc @@ -58,6 +58,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); +static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); /* D attribute handlers for user defined attributes. */ static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *); @@ -80,6 +81,7 @@ static tree d_handle_restrict_attribute (tree *, tree, tree, int, bool *); static tree d_handle_used_attribute (tree *, tree, tree, int, bool *); static tree d_handle_visibility_attribute (tree *, tree, tree, int, bool *); static tree d_handle_no_sanitize_attribute (tree *, tree, tree, int, bool *); +static tree d_handle_simd_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -186,6 +188,8 @@ const attribute_spec d_langhook_common_attribute_table[] = handle_type_generic_attribute, NULL), ATTR_SPEC ("fn spec", 1, 1, false, true, true, false, handle_fnspec_attribute, NULL), + ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false, + handle_omp_declare_simd_attribute, NULL), ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), }; @@ -228,6 +232,8 @@ const attribute_spec d_langhook_attribute_table[] = d_handle_register_attribute, NULL), ATTR_SPEC ("restrict", 0, 0, true, false, false, false, d_handle_restrict_attribute, NULL), + ATTR_SPEC ("simd", 0, 1, true, false, false, false, + d_handle_simd_attribute, NULL), ATTR_SPEC ("used", 0, 0, true, false, false, false, d_handle_used_attribute, NULL), ATTR_SPEC ("visibility", 1, 1, false, false, false, false, @@ -664,6 +670,16 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *) return NULL_TREE; } +/* Handle an "omp declare simd" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + return NULL_TREE; +} + /* Language specific attribute handlers. These functions take the arguments: (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ @@ -1474,6 +1490,55 @@ d_handle_restrict_attribute (tree *node, tree name, tree, int, return NULL_TREE; } +/* Handle a "simd" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +d_handle_simd_attribute (tree *node, tree name, tree args, int, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + return NULL_TREE; + } + + tree omp_attr = get_identifier ("omp declare simd"); + tree omp_flags = NULL_TREE; + if (args) + { + tree id = TREE_VALUE (args); + + if (TREE_CODE (id) != STRING_CST) + { + error ("%qE attribute argument not a string constant", name); + *no_add_attrs = true; + return NULL_TREE; + } + + if (strcmp (TREE_STRING_POINTER (id), "notinbranch") == 0) + omp_flags = build_omp_clause (DECL_SOURCE_LOCATION (*node), + OMP_CLAUSE_NOTINBRANCH); + else if (strcmp (TREE_STRING_POINTER (id), "inbranch") == 0) + omp_flags = build_omp_clause (DECL_SOURCE_LOCATION (*node), + OMP_CLAUSE_INBRANCH); + else + { + error ("only % and % flags are " + "allowed for % attribute"); + *no_add_attrs = true; + return NULL_TREE; + } + } + + DECL_ATTRIBUTES (*node) = + tree_cons (omp_attr, build_tree_list (NULL_TREE, omp_flags), + DECL_ATTRIBUTES (*node)); + + return NULL_TREE; +} + /* Handle a "used" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/testsuite/gdc.dg/attr_simd1.d b/gcc/testsuite/gdc.dg/attr_simd1.d new file mode 100644 index 00000000000..8e83d80b3e0 --- /dev/null +++ b/gcc/testsuite/gdc.dg/attr_simd1.d @@ -0,0 +1,40 @@ +// { dg-do compile } +// { dg-options "-fdump-tree-optimized" } + +import gcc.attributes; + +extern(C) @simd int simd_attr() { return 0; } + +// { dg-final { scan-tree-dump "simd_attr\[ \\t\]simdclone|vector" "optimized" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVbN4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVbM4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVcN4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVcM4_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVdN8_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVdM8_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVeN16_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVeM16_simd_attr:" 1 { target { i?86-*-* x86_64-*-* } } } } + +extern(C) @simd_clones("notinbranch") int simd_notinbranch() { return 0; } + +// { dg-final { scan-tree-dump "simd_notinbranch\[ \\t\]simdclone|vector" "optimized" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVbN4_simd_notinbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVcN4_simd_notinbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVdN8_simd_notinbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVeN16_simd_notinbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVbM4_simd_notinbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVcM4_simd_notinbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVdM8_simd_notinbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVeM16_simd_notinbranch:" { target { i?86-*-* x86_64-*-* } } } } + +extern(C) @simd_clones("inbranch") int simd_inbranch() { return 0; } + +// { dg-final { scan-tree-dump "simd_inbranch\[ \\t\]simdclone|vector" "optimized" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVbN4_simd_inbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVcN4_simd_inbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVdN8_simd_inbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-not "_ZGVeN16_simd_inbranch:" { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVbM4_simd_inbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVcM4_simd_inbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVdM8_simd_inbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } +// { dg-final { scan-assembler-times "_ZGVeM16_simd_inbranch:" 1 { target { i?86-*-* x86_64-*-* } } } } diff --git a/gcc/testsuite/gdc.dg/attr_simd2.d b/gcc/testsuite/gdc.dg/attr_simd2.d new file mode 100644 index 00000000000..49cb6421fab --- /dev/null +++ b/gcc/testsuite/gdc.dg/attr_simd2.d @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-options "-fdump-tree-optimized" } + +import gcc.attributes; + +@attribute("simd") +int simd_ignored; // { dg-warning ".simd. attribute ignored" } + +@attribute("simd", 123) +int simd_string() { return 0; } // { dg-error ".simd. attribute argument not a string constant" } + +@attribute("simd", "invalid") +int simd_invalid() { return 0; } // { dg-error "only .inbranch. and .notinbranch. flags are allowed for .simd. attribute" } + +@attribute("simd", "notinbranch", "inbranch") +int simd_wrong_args() { return 0; } // { dg-error "wrong number of arguments specified for .simd. attribute" } diff --git a/libphobos/libdruntime/gcc/attributes.d b/libphobos/libdruntime/gcc/attributes.d index 40a18bfa947..9d7f2e1d861 100644 --- a/libphobos/libdruntime/gcc/attributes.d +++ b/libphobos/libdruntime/gcc/attributes.d @@ -371,6 +371,46 @@ auto section(A...)(A arguments) assert(false, "section attribute argument not a string constant"); } +/** + * The `@simd` attribute enables creation of one or more function versions that + * can process multiple arguments using SIMD instructions from a single + * invocation. Specifying this attribute allows compiler to assume that such + * versions are available at link time (provided in the same or another module). + * Generated versions are target-dependent and described in the corresponding + * Vector ABI document. For x86_64 target this document can be found here. + * https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt + * + * The `@simd_clones` attribute is the same as `@simd`, but also includes a + * `mask` argument. Valid masks values are `notinbranch` or `inbranch`, and + * instructs the compiler to generate non-masked or masked clones + * correspondingly. + * + * Example: + * --- + * import gcc.attributes; + * + * @simd double sqrt(double x); + * @simd("notinbranch") double atan2(double y, double x); + * --- + */ +enum simd = attribute("simd"); + +auto simd_clones(string mask) +{ + if (mask == "notinbranch" || mask == "inbranch") + return attribute("simd", mask); + else + { + assert(false, "unrecognized parameter `" ~ mask + ~ "` for `gcc.attribute.simd_clones`"); + } +} + +auto simd_clones(A...)(A arguments) +{ + assert(false, "simd_clones attribute argument not a string constant"); +} + /** * The `@symver` attribute creates a symbol version on ELF targets. The syntax * of the string parameter is `name@nodename`. The `name` part of the parameter