From patchwork Tue Nov 14 14:15:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kito Cheng X-Patchwork-Id: 164943 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b909:0:b0:403:3b70:6f57 with SMTP id t9csp1890801vqg; Tue, 14 Nov 2023 06:15:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IGTdktRfT7+AP7NfXGZ6pvhNVF1tUAs5JoPsknI/WPsMUl35Z89k5jnXQGglKyp9QZebnQT X-Received: by 2002:ac8:5d86:0:b0:41e:279d:ddc0 with SMTP id d6-20020ac85d86000000b0041e279dddc0mr2622044qtx.40.1699971355976; Tue, 14 Nov 2023 06:15:55 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1699971355; cv=pass; d=google.com; s=arc-20160816; b=xhwYyrEFI7xU5b/3yg+7ZmHGtPRfjpiEC7GuRw4L8NBF1gtDbnA3NFkiprsJEUU7X3 jdkCPTV7Bqe02uRWMAPsonOHjf3WXag2K7WKNkPu8WTPwt67Y9/lJ+I8olGHGRqvh+SX vhC8TifkcM/jA5P20QlBJ7vleqRNkniepyHl84dhUeqXr+GiVJAY+twWjDDKCaUSbjLE hqiq9gpRa8Dy8JmIO2J3tNpOpgUlIB/sjdAGIKNGk3OpA5VxWWS33jyZN50y0lJPL3YD I9zonbfNSWZ8D/id9ubx0EyZ7MWVhgjf0jDPuSaOl4YZA1+XxCX9ikAnpfMMbbdJ+fLR OI7g== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dkim-signature :arc-filter:dmarc-filter:delivered-to; bh=Kek6pgNkMaOcOXbEuHfwZGAQP0vPjoXAzCT0Ok9cjNk=; fh=8T25ejDQszIv0XIV+uHFl0ltUz+jjClOs2mp1gTMpKA=; b=TR8AcK4/JZgF3I+xcPfszKW5MRwNhBgq5ful2SR6Ytl2gjGmu02Y0ynqxZxdknpJME veoFjxoB9PgjMTAJarNDGHxkiQ+1d6wzGL5I8ClQ+5V0G+605j7oalhoIzKmdye/sKpk rrghzLnHzF/KnDOwrfDHfustb0FGsDpYxRYGXPEKvDwLxdA9sU5IaZl7H4JdF3OPIXtD dPyOT6PLbRrHREUIznlrpWp6UCc8MgU4p5FaSMwCetcVZSTRQmNg7reQyh9yAlLuF8kq gHQlces1koqDsBqyvnluiZiWbtwepoduA++bliSOQb1PhX2Pgv8N2/10ykKvz9Ti1M68 SPPA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@sifive.com header.s=google header.b=V8uxixMq; arc=pass (i=1); 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=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id n13-20020ac85a0d000000b0041fe47da9f8si6738957qta.49.2023.11.14.06.15.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Nov 2023 06:15:55 -0800 (PST) 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=@sifive.com header.s=google header.b=V8uxixMq; arc=pass (i=1); 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=REJECT sp=REJECT dis=NONE) header.from=sifive.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AB0933857704 for ; Tue, 14 Nov 2023 14:15:55 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id BFD953857806 for ; Tue, 14 Nov 2023 14:15:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BFD953857806 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=sifive.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BFD953857806 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::635 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699971330; cv=none; b=mZ8XXaek3fEbL+Vkoqd/mhI3m/BQyFyzNaIA7u2EeZY5FmXNvxFed0TSNNvY4KhX4E1hVUK2WXnydog8wBpucDM2bWu6YJUfSyuwxYyD2uDIw14cEAlNKzRBme0Fevg3uU0MwYxqT4UMkbCGB9TwmlqMP2/lYNUFYJwM08C9Ed8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699971330; c=relaxed/simple; bh=SGHGWunIaRIaU64+KkZv39PN8odFb9+l3AjEXzay7oc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=njUrW/JounAJPNyV2Aof8LbIEfrUvmvtX5WYAjWKDsmIJzemSmyWZ+pLKl7PgW9GJyFHSChooPPw0+24ipfIHgGp89Wsh4VehFw+jE0TiiA7jPEwTFioSFFj4XIPtcCSXMyn13b+X2INGTOvy1g/zyMSP0m5AF1irNEujT6LvFU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1cc0d0a0355so42851165ad.3 for ; Tue, 14 Nov 2023 06:15:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; t=1699971323; x=1700576123; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Kek6pgNkMaOcOXbEuHfwZGAQP0vPjoXAzCT0Ok9cjNk=; b=V8uxixMq+2fvRDIWxIUPRx9YRcAsbRAPu6RlMBJ08Z+AVjr7BBgW0OSJqxIRNQaXso 5Kb02l2OAhPwFjk44G0q3acShtpxl8sMAYIVdxKJWaJvw58M0KRNNsU5PVLpbcD6Mhs5 XcueET1VXavbHXlcLYF84+msvDpYHB8OnP5RKMK04i5nXPz6rNRMdxeCq2YVg3Bui5Gk pnINdnSNF51fLFyfocCGeoFO8MZ24ONRwFLBAf0A1LLWEDw5OJ1e6YMqBYgiuskMVOdn Nheh4mIxvpEus37Aqa6x+zlR5dgiy5fdUDhqCK+3/8It2xp4nKwhK67PGsDOPzLg0l6J aCLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699971323; x=1700576123; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Kek6pgNkMaOcOXbEuHfwZGAQP0vPjoXAzCT0Ok9cjNk=; b=gBtRDYVN4BLBMphmyfhV/6+M+uYem9taVw5cmo/rJjzKUS8eFENotd70g/4ZOdjkpR g4gGKUJ4yTWFKZ1WSMNlIzpYWCeRgrE0aCUKmEV7M5EpyAx4CWzlXXh7oFY/HbXobXjN K+R5v0vFUUGy6yrRO4gDNPup0nAwoIs8qj03ZoL+H1OgB5ba2XWoWt47K0wsafo62UoP jtYGV5B9v3GtF1YLJ4/hxxRxyI271/MGIatNz8lU1lyzx0exFj5JrYO9VLL0aX2snKcq e8rNbPxnCVFKVEGTk7Iyom6p9Ca1vgjwU7J4fuVne6D54aeQ9hyTf+zbs11U2RQPY0f+ UzMQ== X-Gm-Message-State: AOJu0YwhO3UvjmJ6mQWyI1rCDJrD3avyJmz1ii/GOwyPhf7kEUfiHJfY EAPNATNtZgYb0WF1D790iuDgC4RSsOCW7nzXs0Tk247M4PeJAII+YrtoywKMPTJv8DBIMx1IyiH Oumx4i40+0Kxtlrq0dFgFe34DHUl8mNlSfMIdUfNNsP66w6EjBLCESXIL5DZ04A5UV1rLaI5oz7 7vygo= X-Received: by 2002:a17:902:b595:b0:1c7:49dd:2df with SMTP id a21-20020a170902b59500b001c749dd02dfmr1996419pls.32.1699971321444; Tue, 14 Nov 2023 06:15:21 -0800 (PST) Received: from hsinchu02.internal.sifive.com (59-124-168-89.hinet-ip.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id b16-20020a170903229000b001c3be750900sm5682893plh.163.2023.11.14.06.15.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 14 Nov 2023 06:15:20 -0800 (PST) From: Kito Cheng To: gcc-patches@gcc.gnu.org, kito.cheng@gmail.com, palmer@dabbelt.com, jeffreyalaw@gmail.com Cc: Kito Cheng Subject: [PATCH v2] RISC-V: Implement target attribute Date: Tue, 14 Nov 2023 22:15:13 +0800 Message-Id: <20231114141513.24515-1-kito.cheng@sifive.com> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 X-Spam-Status: No, score=-12.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1782549164406327033 X-GMAIL-MSGID: 1782549164406327033 The target attribute which proposed in [1], target attribute allow user to specify a local setting per-function basis. The syntax of target attribute is `__attribute__((target("")))`. and the syntax of `` describes below: ``` ATTR-STRING := ATTR-STRING ';' ATTR | ATTR ATTR := ARCH-ATTR | CPU-ATTR | TUNE-ATTR ARCH-ATTR := 'arch=' EXTENSIONS-OR-FULLARCH EXTENSIONS-OR-FULLARCH := | EXTENSIONS := ',' | FULLARCHSTR := EXTENSION := OP := '+' VERSION := [0-9]+ 'p' [0-9]+ | [1-9][0-9]* | EXTENSION-NAME := Naming rule is defined in RISC-V ISA manual CPU-ATTR := 'cpu=' TUNE-ATTR := 'tune=' ``` Changes since v1: - Use std::unique_ptr rather than alloca to prevent memory issue. - Error rather than warning when attribute duplicated. [1] https://github.com/riscv-non-isa/riscv-c-api-doc/pull/35 gcc/ChangeLog: * config.gcc (riscv): Add riscv-target-attr.o. * config/riscv/riscv-protos.h (riscv_declare_function_size) New. (riscv_option_valid_attribute_p): New. (riscv_override_options_internal): New. (struct riscv_tune_info): New. (riscv_parse_tune): New. * config/riscv/riscv-target-attr.cc (class riscv_target_attr_parser): New. (struct riscv_attribute_info): New. (riscv_attributes): New. (riscv_target_attr_parser::parse_arch): (riscv_target_attr_parser::handle_arch): (riscv_target_attr_parser::handle_cpu): (riscv_target_attr_parser::handle_tune): (riscv_target_attr_parser::update_settings): (riscv_process_one_target_attr): (num_occurences_in_str): (riscv_process_target_attr): (riscv_option_valid_attribute_p): * config/riscv/riscv.cc: Include target-globals.h and riscv-subset.h. (struct riscv_tune_info): Move to riscv-protos.h. (get_tune_str): (riscv_parse_tune): (riscv_declare_function_size): (riscv_option_override): Build target_option_default_node and target_option_current_node. (riscv_save_restore_target_globals): (riscv_option_restore): (riscv_previous_fndecl): (riscv_set_current_function): Apply the target attribute. (TARGET_OPTION_RESTORE): Define. (TARGET_OPTION_VALID_ATTRIBUTE_P): Ditto. * config/riscv/riscv.h (SWITCHABLE_TARGET): Define to 1. (ASM_DECLARE_FUNCTION_SIZE) Define. * config/riscv/riscv.opt (mtune=): Add Save attribute. (mcpu=): Ditto. (mcmodel=): Ditto. * config/riscv/t-riscv: Add build rule for riscv-target-attr.o * doc/extend.texi: Add doc for target attribute. gcc/testsuite/ChangeLog: * gcc.target/riscv/target-attr-01.c: New. * gcc.target/riscv/target-attr-02.c: Ditto. * gcc.target/riscv/target-attr-03.c: Ditto. * gcc.target/riscv/target-attr-04.c: Ditto. * gcc.target/riscv/target-attr-05.c: Ditto. * gcc.target/riscv/target-attr-06.c: Ditto. * gcc.target/riscv/target-attr-07.c: Ditto. * gcc.target/riscv/target-attr-bad-01.c: Ditto. * gcc.target/riscv/target-attr-bad-02.c: Ditto. * gcc.target/riscv/target-attr-bad-03.c: Ditto. * gcc.target/riscv/target-attr-bad-04.c: Ditto. * gcc.target/riscv/target-attr-bad-05.c: Ditto. * gcc.target/riscv/target-attr-bad-06.c: Ditto. * gcc.target/riscv/target-attr-bad-07.c: Ditto. * gcc.target/riscv/target-attr-bad-08.c: Ditto. * gcc.target/riscv/target-attr-bad-09.c: Ditto. * gcc.target/riscv/target-attr-bad-10.c: Ditto. --- gcc/config.gcc | 2 +- gcc/config/riscv/riscv-protos.h | 21 + gcc/config/riscv/riscv-target-attr.cc | 395 ++++++++++++++++++ gcc/config/riscv/riscv.cc | 192 +++++++-- gcc/config/riscv/riscv.h | 6 + gcc/config/riscv/riscv.opt | 6 +- gcc/config/riscv/t-riscv | 5 + gcc/doc/extend.texi | 58 +++ .../gcc.target/riscv/target-attr-01.c | 31 ++ .../gcc.target/riscv/target-attr-02.c | 31 ++ .../gcc.target/riscv/target-attr-03.c | 26 ++ .../gcc.target/riscv/target-attr-04.c | 28 ++ .../gcc.target/riscv/target-attr-05.c | 27 ++ .../gcc.target/riscv/target-attr-06.c | 27 ++ .../gcc.target/riscv/target-attr-07.c | 25 ++ .../gcc.target/riscv/target-attr-bad-01.c | 13 + .../gcc.target/riscv/target-attr-bad-02.c | 13 + .../gcc.target/riscv/target-attr-bad-03.c | 13 + .../gcc.target/riscv/target-attr-bad-04.c | 13 + .../gcc.target/riscv/target-attr-bad-05.c | 13 + .../gcc.target/riscv/target-attr-bad-06.c | 13 + .../gcc.target/riscv/target-attr-bad-07.c | 13 + .../gcc.target/riscv/target-attr-bad-08.c | 8 + .../gcc.target/riscv/target-attr-bad-09.c | 8 + .../gcc.target/riscv/target-attr-bad-10.c | 8 + 25 files changed, 950 insertions(+), 45 deletions(-) create mode 100644 gcc/config/riscv/riscv-target-attr.cc create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-01.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-02.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-03.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-04.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-05.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-06.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-07.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-01.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-02.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-03.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-04.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-05.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-06.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-07.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-08.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-09.c create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-bad-10.c diff --git a/gcc/config.gcc b/gcc/config.gcc index ba6d63e33ac..0e86e60629e 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -546,7 +546,7 @@ riscv*) extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o riscv-string.o" extra_objs="${extra_objs} riscv-v.o riscv-vsetvl.o riscv-vector-costs.o riscv-avlprop.o" extra_objs="${extra_objs} riscv-vector-builtins.o riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o" - extra_objs="${extra_objs} thead.o" + extra_objs="${extra_objs} thead.o riscv-target-attr.o" d_target_objs="riscv-d.o" extra_headers="riscv_vector.h" target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc" diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 8cdfadbcf10..196b53f10f3 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -124,6 +124,7 @@ extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_return (); extern void riscv_declare_function_name (FILE *, const char *, tree); +extern void riscv_declare_function_size (FILE *, const char *, tree); extern void riscv_asm_output_alias (FILE *, const tree, const tree); extern void riscv_asm_output_external (FILE *, const tree, const char *); extern bool @@ -647,5 +648,25 @@ extern bool th_print_operand_address (FILE *, machine_mode, rtx); extern bool riscv_use_divmod_expander (void); void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); +extern bool +riscv_option_valid_attribute_p (tree, tree, tree, int); +extern void +riscv_override_options_internal (struct gcc_options *); + +struct riscv_tune_param; +/* Information about one micro-arch we know about. */ +struct riscv_tune_info { + /* This micro-arch canonical name. */ + const char *name; + + /* Which automaton to use for tuning. */ + enum riscv_microarchitecture_type microarchitecture; + + /* Tuning parameters for this micro-arch. */ + const struct riscv_tune_param *tune_param; +}; + +const struct riscv_tune_info * +riscv_parse_tune (const char *, bool); #endif /* ! GCC_RISCV_PROTOS_H */ diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc new file mode 100644 index 00000000000..78f259d0c96 --- /dev/null +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -0,0 +1,395 @@ +/* Subroutines used for parsing target attribute for RISC-V. + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#define IN_TARGET_CODE 1 + +#define INCLUDE_MEMORY +#define INCLUDE_STRING +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "tm_p.h" +#include "diagnostic.h" +#include "opts.h" +#include "riscv-subset.h" + +namespace { +class riscv_target_attr_parser +{ +public: + riscv_target_attr_parser (location_t loc) + : m_found_arch_p (false) + , m_found_tune_p (false) + , m_found_cpu_p (false) + , m_subset_list (nullptr) + , m_loc (loc) + , m_cpu_info (nullptr) + , m_tune (nullptr) + { + } + + bool handle_arch (const char *); + bool handle_cpu (const char *); + bool handle_tune (const char *); + + void set_loc (location_t loc) { + m_loc = loc; + } + + void update_settings (struct gcc_options *opts) const; +private: + const char *m_raw_attr_str; + bool parse_arch (const char *); + + bool m_found_arch_p; + bool m_found_tune_p; + bool m_found_cpu_p; + riscv_subset_list *m_subset_list; + location_t m_loc; + const riscv_cpu_info *m_cpu_info; + const char *m_tune; +}; +} + +/* All the information needed to handle a target attribute. + NAME is the name of the attribute. + HANDLER is the function that takes the attribute string as an argument. */ + +struct riscv_attribute_info +{ + const char *name; + bool (riscv_target_attr_parser::*handler) (const char *); +}; + +/* The target attributes that we support. */ + +static const struct riscv_attribute_info riscv_attributes[] + = {{"arch", &riscv_target_attr_parser::handle_arch}, + {"cpu", &riscv_target_attr_parser::handle_cpu}, + {"tune", &riscv_target_attr_parser::handle_tune}}; + +bool +riscv_target_attr_parser::parse_arch (const char *str) +{ + if (m_subset_list) + delete m_subset_list; + /* Check if it's setting full arch string. */ + if (strncmp ("rv", str, strlen ("rv")) == 0) + { + m_subset_list = riscv_subset_list::parse (str, location_t ()); + + if (m_subset_list == nullptr) + goto fail; + + return true; + } + else + { + /* Parsing the extension list like "+[,+]*". */ + size_t len = strlen (str); + std::unique_ptr buf (new char[len]); + char *str_to_check = buf.get (); + strcpy (str_to_check, str); + const char *token = strtok_r (str_to_check, ",", &str_to_check); + m_subset_list = riscv_current_subset_list ()->clone (); + m_subset_list->set_loc (m_loc); + while (token) + { + if (token[0] != '+') + { + error_at ( + m_loc, + "unexpected arch for % attribute: must start " + "with + or rv"); + goto fail; + } + else + { + const char *result = m_subset_list->parse_single_ext (token + 1); + /* Check parse_single_ext has consume all string. */ + if (*result != '\0') + { + error_at ( + m_loc, + "unexpected arch for % attribute: bad " + "string found %<%s%>", token); + goto fail; + } + } + token = strtok_r (NULL, ",", &str_to_check); + } + return true; + } +fail: + if (m_subset_list != nullptr) + { + delete m_subset_list; + m_subset_list = nullptr; + } + return false; +} + +/* Handle the ARCH_STR argument to the arch= target attribute. */ + +bool +riscv_target_attr_parser::handle_arch (const char *str) +{ + if (m_found_arch_p) + error_at (m_loc, "% attribute: arch appears more than once"); + m_found_arch_p = true; + return parse_arch (str); +} + +/* Handle the CPU_STR argument to the cpu= target attribute. */ + +bool +riscv_target_attr_parser::handle_cpu (const char *str) +{ + if (m_found_cpu_p) + error_at (m_loc, "% attribute: cpu appears more than once"); + + m_found_cpu_p = true; + const riscv_cpu_info *cpu_info = riscv_find_cpu (str); + + if (!cpu_info) + { + error_at (m_loc, "% attribute: unknown CPU %qs", str); + return false; + } + + if (m_subset_list == nullptr) + { + const char *arch_str = cpu_info->arch; + m_subset_list = riscv_subset_list::parse (arch_str, m_loc); + gcc_assert (m_subset_list); + } + + m_cpu_info = cpu_info; + return true; +} + +/* Handle the TUNE_STR argument to the tune= target attribute. */ + +bool +riscv_target_attr_parser::handle_tune (const char *str) +{ + if (m_found_tune_p) + error_at (m_loc, "% attribute: tune appears more than once"); + m_found_tune_p = true; + const struct riscv_tune_info *tune = riscv_parse_tune (str, true); + + if (tune == nullptr) + { + error_at (m_loc, "% attribute: unknown TUNE %qs", str); + return false; + } + + m_tune = tune->name; + + return true; +} + +void +riscv_target_attr_parser::update_settings (struct gcc_options *opts) const +{ + if (m_subset_list) + riscv_set_arch_by_subset_list (m_subset_list, opts); + + if (m_cpu_info) + opts->x_riscv_cpu_string = m_cpu_info->name; + + if (m_tune) + opts->x_riscv_tune_string = m_tune; + else + { + if (m_cpu_info) + opts->x_riscv_tune_string = m_cpu_info->tune; + } +} + +/* Parse ARG_STR which contains the definition of one target attribute. + Show appropriate errors if any or return true if the attribute is valid. */ + +static bool +riscv_process_one_target_attr (char *arg_str, + location_t loc, + riscv_target_attr_parser &attr_parser) +{ + size_t len = strlen (arg_str); + + if (len == 0) + { + error_at (loc, "malformed % attribute"); + return false; + } + + std::unique_ptr buf (new char[len]); + char *str_to_check = buf.get(); + strcpy (str_to_check, arg_str); + + char *arg = strchr (str_to_check, '='); + + if (!arg) + { + error_at ( + loc, + "attribute % does not accept an argument", + str_to_check); + return false; + } + + arg[0] = '\0'; + ++arg; + for (const auto &attr : riscv_attributes) + { + /* If the names don't match up, or the user has given an argument + to an attribute that doesn't accept one, or didn't give an argument + to an attribute that expects one, fail to match. */ + if (strncmp (str_to_check, attr.name, strlen (attr.name)) != 0) + continue; + + return (&attr_parser->*attr.handler) (arg); + } + error_at (loc, "Got unknown attribute %", str_to_check); + + return false; +} + +/* Count how many times the character C appears in + NULL-terminated string STR. */ + +static unsigned int +num_occurences_in_str (char c, char *str) +{ + unsigned int res = 0; + while (*str != '\0') + { + if (*str == c) + res++; + + str++; + } + + return res; +} + +/* Parse the tree in ARGS that contains the target attribute information + and update the global target options space. */ + +static bool +riscv_process_target_attr (tree args, location_t loc, struct gcc_options *opts) +{ + if (TREE_CODE (args) == TREE_LIST) + { + do + { + tree head = TREE_VALUE (args); + if (head) + { + if (!riscv_process_target_attr (head, loc, opts)) + return false; + } + args = TREE_CHAIN (args); + } while (args); + + return true; + } + + if (TREE_CODE (args) != STRING_CST) + { + error_at (loc, "attribute % argument not a string"); + return false; + } + size_t len = strlen (TREE_STRING_POINTER (args)); + + /* No need to emit warning or error on empty string here, generic code already + handle this case. */ + if (len == 0) + { + return false; + } + + std::unique_ptr buf (new char[len]); + char *str_to_check = buf.get (); + strcpy (str_to_check, TREE_STRING_POINTER (args)); + + /* Used to catch empty spaces between commas i.e. + attribute ((target ("attr1;;attr2"))). */ + unsigned int num_commas = num_occurences_in_str (';', str_to_check); + + /* Handle multiple target attributes separated by ','. */ + char *token = strtok_r (str_to_check, ";", &str_to_check); + + riscv_target_attr_parser attr_parser (loc); + unsigned int num_attrs = 0; + while (token) + { + num_attrs++; + riscv_process_one_target_attr (token, loc, attr_parser); + token = strtok_r (NULL, ";", &str_to_check); + } + + if (num_attrs != num_commas + 1) + { + error_at (loc, "malformed % attribute", + TREE_STRING_POINTER (args)); + return false; + } + + /* Apply settings from target attribute. */ + attr_parser.update_settings (opts); + + return true; +} + +/* Implement TARGET_OPTION_VALID_ATTRIBUTE_P. This is used to + process attribute ((target ("..."))). */ + +bool +riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int) +{ + struct cl_target_option cur_target; + bool ret; + tree new_target; + location_t loc = DECL_SOURCE_LOCATION (fndecl); + + /* Save the current target options to restore at the end. */ + cl_target_option_save (&cur_target, &global_options, &global_options_set); + + ret = riscv_process_target_attr (args, loc, &global_options); + + if (ret) + { + riscv_override_options_internal (&global_options); + new_target + = build_target_option_node (&global_options, &global_options_set); + } + else + new_target = NULL; + + if (fndecl && ret) + { + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; + } + + cl_target_option_restore (&global_options, &global_options_set, &cur_target); + return ret; +} diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f09c4066903..cebd2fc0d25 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -73,10 +73,12 @@ along with GCC; see the file COPYING3. If not see #include "tree-vectorizer.h" #include "gcse.h" #include "tree-dfa.h" +#include "target-globals.h" /* This file should be included last. */ #include "target-def.h" #include "riscv-vector-costs.h" +#include "riscv-subset.h" /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ @@ -264,17 +266,6 @@ struct riscv_tune_param bool use_divmod_expansion; }; -/* Information about one micro-arch we know about. */ -struct riscv_tune_info { - /* This micro-arch canonical name. */ - const char *name; - - /* Which automaton to use for tuning. */ - enum riscv_microarchitecture_type microarchitecture; - - /* Tuning parameters for this micro-arch. */ - const struct riscv_tune_param *tune_param; -}; /* Global variables for machine-dependent things. */ @@ -501,10 +492,23 @@ riscv_min_arithmetic_precision (void) return 32; } -/* Return the riscv_tune_info entry for the given name string. */ +template +static const char * +get_tune_str (const T *opts) +{ + const char *tune_string = RISCV_TUNE_STRING_DEFAULT; + if (opts->x_riscv_tune_string) + tune_string = opts->x_riscv_tune_string; + else if (opts->x_riscv_cpu_string) + tune_string = opts->x_riscv_cpu_string; + return tune_string; +} + +/* Return the riscv_tune_info entry for the given name string, return nullptr + if NULL_P is true, otherwise return an placeholder and report error. */ -static const struct riscv_tune_info * -riscv_parse_tune (const char *tune_string) +const struct riscv_tune_info * +riscv_parse_tune (const char *tune_string, bool null_p) { const riscv_cpu_info *cpu = riscv_find_cpu (tune_string); @@ -515,6 +519,9 @@ riscv_parse_tune (const char *tune_string) if (strcmp (riscv_tune_info_table[i].name, tune_string) == 0) return riscv_tune_info_table + i; + if (null_p) + return nullptr; + error ("unknown cpu %qs for %<-mtune%>", tune_string); return riscv_tune_info_table; } @@ -7873,6 +7880,33 @@ riscv_declare_function_name (FILE *stream, const char *name, tree fndecl) riscv_asm_output_variant_cc (stream, fndecl, name); ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function"); ASM_OUTPUT_LABEL (stream, name); + if (DECL_FUNCTION_SPECIFIC_TARGET (fndecl)) + { + fprintf (stream, "\t.option push\n"); + std::string isa = riscv_current_subset_list ()->to_string (true); + fprintf (stream, "\t.option arch, %s\n", isa.c_str ()); + + struct cl_target_option *local_cl_target = + TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (fndecl)); + struct cl_target_option *global_cl_target = + TREE_TARGET_OPTION (target_option_default_node); + const char *local_tune_str = get_tune_str (local_cl_target); + const char *global_tune_str = get_tune_str (global_cl_target); + if (strcmp (local_tune_str, global_tune_str) != 0) + fprintf (stream, "\t# tune = %s\n", local_tune_str); + } +} + +void +riscv_declare_function_size (FILE *stream, const char *name, tree fndecl) +{ + if (!flag_inhibit_size_directive) + ASM_OUTPUT_MEASURED_SIZE (stream, name); + + if (DECL_FUNCTION_SPECIFIC_TARGET (fndecl)) + { + fprintf (stream, "\t.option pop\n"); + } } /* Implement ASM_OUTPUT_DEF_FROM_DECLS. */ @@ -8079,16 +8113,18 @@ riscv_override_options_internal (struct gcc_options *opts) error ("%<-mdiv%> requires %<-march%> to subsume the % extension"); /* Likewise floating-point division and square root. */ - if ((TARGET_HARD_FLOAT || TARGET_ZFINX) && (target_flags_explicit & MASK_FDIV) == 0) + if ((TARGET_HARD_FLOAT_OPTS_P (opts) || TARGET_ZFINX_OPTS_P (opts)) + && ((target_flags_explicit & MASK_FDIV) == 0)) opts->x_target_flags |= MASK_FDIV; /* Handle -mtune, use -mcpu if -mtune is not given, and use default -mtune if both -mtune and -mcpu are not given. */ - cpu = riscv_parse_tune (opts->x_riscv_tune_string ? opts->x_riscv_tune_string : - (opts->x_riscv_cpu_string ? opts->x_riscv_cpu_string : - RISCV_TUNE_STRING_DEFAULT)); + const char *tune_string = get_tune_str (opts); + cpu = riscv_parse_tune (tune_string, false); riscv_microarchitecture = cpu->microarchitecture; - tune_param = opts->x_optimize_size ? &optimize_size_tune_info : cpu->tune_param; + tune_param = opts->x_optimize_size + ? &optimize_size_tune_info + : cpu->tune_param; /* Use -mtune's setting for slow_unaligned_access, even when optimizing for size. For architectures that trap and emulate unaligned accesses, @@ -8100,7 +8136,7 @@ riscv_override_options_internal (struct gcc_options *opts) /* Make a note if user explicity passed -mstrict-align for later builtin macro generation. Can't use target_flags_explicitly since it is set even for -mno-strict-align. */ - riscv_user_wants_strict_align = TARGET_STRICT_ALIGN; + riscv_user_wants_strict_align = TARGET_STRICT_ALIGN_OPTS_P (opts); if ((target_flags_explicit & MASK_STRICT_ALIGN) == 0 && cpu->tune_param->slow_unaligned_access) @@ -8258,8 +8294,41 @@ riscv_option_override (void) init_machine_status = &riscv_init_machine_status; riscv_override_options_internal (&global_options); + + /* Save these options as the default ones in case we push and pop them later + while processing functions with potential target attributes. */ + target_option_default_node = target_option_current_node + = build_target_option_node (&global_options, &global_options_set); +} + +/* Restore or save the TREE_TARGET_GLOBALS from or to NEW_TREE. + Used by riscv_set_current_function to + make sure optab availability predicates are recomputed when necessary. */ + +void +riscv_save_restore_target_globals (tree new_tree) +{ + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else if (new_tree == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); } +/* Implements TARGET_OPTION_RESTORE. Restore the backend codegen decisions + using the information saved in PTR. */ + +static void +riscv_option_restore (struct gcc_options *opts, + struct gcc_options * /* opts_set */, + struct cl_target_option * /* ptr */) +{ + riscv_override_options_internal (opts); +} + +static GTY (()) tree riscv_previous_fndecl; + /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ static void @@ -8505,7 +8574,12 @@ riscv_get_interrupt_type (tree decl) return MACHINE_MODE; } -/* Implement `TARGET_SET_CURRENT_FUNCTION'. */ +/* Implement `TARGET_SET_CURRENT_FUNCTION'. Unpack the codegen decisions + like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET + of the function, if such exists. This function may be called multiple + times on a single function so use aarch64_previous_fndecl to avoid + setting up identical state. */ + /* Sanity cheching for above function attributes. */ static void riscv_set_current_function (tree decl) @@ -8513,36 +8587,66 @@ riscv_set_current_function (tree decl) if (decl == NULL_TREE || current_function_decl == NULL_TREE || current_function_decl == error_mark_node - || ! cfun->machine - || cfun->machine->attributes_checked_p) + || ! cfun->machine) return; - cfun->machine->naked_p = riscv_naked_function_p (decl); - cfun->machine->interrupt_handler_p - = riscv_interrupt_type_p (TREE_TYPE (decl)); + if (!cfun->machine->attributes_checked_p) + { + cfun->machine->naked_p = riscv_naked_function_p (decl); + cfun->machine->interrupt_handler_p + = riscv_interrupt_type_p (TREE_TYPE (decl)); - if (cfun->machine->naked_p && cfun->machine->interrupt_handler_p) - error ("function attributes %qs and %qs are mutually exclusive", - "interrupt", "naked"); + if (cfun->machine->naked_p && cfun->machine->interrupt_handler_p) + error ("function attributes %qs and %qs are mutually exclusive", + "interrupt", "naked"); - if (cfun->machine->interrupt_handler_p) - { - tree ret = TREE_TYPE (TREE_TYPE (decl)); - tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); + if (cfun->machine->interrupt_handler_p) + { + tree ret = TREE_TYPE (TREE_TYPE (decl)); + tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); + + if (TREE_CODE (ret) != VOID_TYPE) + error ("%qs function cannot return a value", "interrupt"); - if (TREE_CODE (ret) != VOID_TYPE) - error ("%qs function cannot return a value", "interrupt"); + if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE) + error ("%qs function cannot have arguments", "interrupt"); - if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE) - error ("%qs function cannot have arguments", "interrupt"); + cfun->machine->interrupt_mode = riscv_get_interrupt_type (decl); - cfun->machine->interrupt_mode = riscv_get_interrupt_type (decl); + gcc_assert (cfun->machine->interrupt_mode != UNKNOWN_MODE); + } - gcc_assert (cfun->machine->interrupt_mode != UNKNOWN_MODE); + /* Don't print the above diagnostics more than once. */ + cfun->machine->attributes_checked_p = 1; } - /* Don't print the above diagnostics more than once. */ - cfun->machine->attributes_checked_p = 1; + if (!decl || decl == riscv_previous_fndecl) + return; + + tree old_tree = (riscv_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (riscv_previous_fndecl) + : NULL_TREE); + + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (decl); + + /* If current function has no attributes but the previous one did, + use the default node. */ + if (!new_tree && old_tree) + new_tree = target_option_default_node; + + /* If nothing to do, return. #pragma GCC reset or #pragma GCC pop to + the default have been handled by aarch64_save_restore_target_globals from + aarch64_pragma_target_parse. */ + if (old_tree == new_tree) + return; + + riscv_previous_fndecl = decl; + + /* First set the target options. */ + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (new_tree)); + + riscv_save_restore_target_globals (new_tree); } /* Implement TARGET_MERGE_DECL_ATTRIBUTES. */ @@ -9664,6 +9768,12 @@ riscv_preferred_else_value (unsigned ifn, tree vectype, unsigned int nops, #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE riscv_option_override +#undef TARGET_OPTION_RESTORE +#define TARGET_OPTION_RESTORE riscv_option_restore + +#undef TARGET_OPTION_VALID_ATTRIBUTE_P +#define TARGET_OPTION_VALID_ATTRIBUTE_P riscv_option_valid_attribute_p + #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS riscv_legitimize_address diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 1e9813b4f39..6205d7533f4 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include #include "config/riscv/riscv-opts.h" +#define SWITCHABLE_TARGET 1 + /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() riscv_cpu_cpp_builtins (pfile) @@ -1056,6 +1058,10 @@ while (0) #define ASM_DECLARE_FUNCTION_NAME(STR, NAME, DECL) \ riscv_declare_function_name (STR, NAME, DECL) +#undef ASM_DECLARE_FUNCTION_SIZE +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + riscv_declare_function_size (FILE, FNAME, DECL) + /* Add output .variant_cc directive for specific alias definition. */ #undef ASM_OUTPUT_DEF_FROM_DECLS #define ASM_OUTPUT_DEF_FROM_DECLS(STR, DECL, TARGET) \ diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 70d78151cee..1bd661a3fe4 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -84,11 +84,11 @@ Target RejectNegative Joined Negative(march=) lower-case. mtune= -Target RejectNegative Joined Var(riscv_tune_string) +Target RejectNegative Joined Var(riscv_tune_string) Save -mtune=PROCESSOR Optimize the output for PROCESSOR. mcpu= -Target RejectNegative Joined Var(riscv_cpu_string) +Target RejectNegative Joined Var(riscv_cpu_string) Save -mcpu=PROCESSOR Use architecture of and optimize the output for PROCESSOR. msmall-data-limit= @@ -106,7 +106,7 @@ memory accesses to be generated as compressed instructions. Currently targets 32-bit integer load/stores. mcmodel= -Target RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL) +Target RejectNegative Joined Enum(code_model) Var(riscv_cmodel) Init(TARGET_DEFAULT_CMODEL) Save Specify the code model. mstrict-align diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv index 95becfc819b..3b9686daa58 100644 --- a/gcc/config/riscv/t-riscv +++ b/gcc/config/riscv/t-riscv @@ -115,6 +115,11 @@ riscv-v.o: $(srcdir)/config/riscv/riscv-v.cc \ $(COMPILE) $< $(POSTCOMPILE) +riscv-target-attr.o: $(srcdir)/config/riscv/riscv-target-attr.cc $(CONFIG_H) \ + $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(DIAGNOSTIC_CORE_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(srcdir)/config/riscv/riscv-target-attr.cc + thead.o: $(srcdir)/config/riscv/thead.cc \ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) backend.h $(RTL_H) \ memmodel.h $(EMIT_RTL_H) poly-int.h output.h diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 7cdfdf8c83b..856dd93d16a 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -6295,8 +6295,66 @@ void f (void) __attribute__ ((interrupt ("user"))); Permissible values for this parameter are @code{user}, @code{supervisor}, and @code{machine}. If there is no parameter, then it defaults to @code{machine}. + +@end table + +The following target-specific function attributes are available for the +RISC-V target. For the most part, these options mirror the behavior of +similar command-line options (@pxref{RISC-V Options}), but on a +per-function basis. + +@table @code +@cindex @code{arch=} function attribute, RISC-V +@item arch= +Specifies the architecture version and architectural extensions to use +for this function. The behavior and permissible arguments are the same as +for the @option{-march=} command-line option, in addtion, it also support +extension enablement list, a list of extension name and prefixed with @code{+}, +like @code{arch=+zba} means enable @code{zba} extension. +Multiple extension can be enabled by separating them with a comma. For example: +@code{arch=+zba,+zbb}. + +@cindex @code{tune=} function attribute, RISC-V +@item tune= +Specifies the core for which to tune the performance of this function. +The behavior and permissible arguments are the same as for the @option{-mtune=} +command-line option. + +@cindex @code{cpu=} function attribute, RISC-V +@item cpu= +Specifies the core for which to tune the performance of this function and also +whose architectural features to use. The behavior and valid arguments are the +same as for the @option{-mcpu=} command-line option. + @end table +The above target attributes can be specified as follows: + +@smallexample +__attribute__((target("@var{attr-string}"))) +int +f (int a) +@{ + return a + 5; +@} +@end smallexample + +where @code{@var{attr-string}} is one of the attribute strings specified above. + +Multiple target function attributes can be specified by separating them with +a semicolon. For example: +@smallexample +__attribute__((target("arch=+zba,+zbb;tune=rocket"))) +int +foo (int a) +@{ + return a + 5; +@} +@end smallexample + +is valid and compiles function @code{foo} with @code{zba} +and @code{zbb} extensions and tunes it for @code{rocket}. + @node RL78 Function Attributes @subsection RL78 Function Attributes diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-01.c b/gcc/testsuite/gcc.target/riscv/target-attr-01.c new file mode 100644 index 00000000000..b3f3d65d543 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-01.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + + +/* +** foo: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ + + +long foo() __attribute__((target("arch=rv64gc_zba"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** slli\s*a1,a1,1 +** add\s*a0,a1,a0 +** ... +*/ + + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-02.c b/gcc/testsuite/gcc.target/riscv/target-attr-02.c new file mode 100644 index 00000000000..c010089a823 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-02.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + + +/* +** foo: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ + + +long foo() __attribute__((target("arch=+zba"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** slli\s*a1,a1,1 +** add\s*a0,a1,a0 +** ... +*/ + + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-03.c b/gcc/testsuite/gcc.target/riscv/target-attr-03.c new file mode 100644 index 00000000000..b4896cb2e27 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-03.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** foo: +** ... +** slli\s*a1,a1,1 +** add\s*a0,a1,a0 +** ... +*/ +long foo() __attribute__((target("arch=rv64gc"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-04.c b/gcc/testsuite/gcc.target/riscv/target-attr-04.c new file mode 100644 index 00000000000..369d6514e5a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-04.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** foo: +** ... +** # tune = sifive-7-series +** ... +** slli\s*a1,a1,1 +** add\s*a0,a1,a0 +** ... +*/ +long foo() __attribute__((target("cpu=sifive-u74"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-05.c b/gcc/testsuite/gcc.target/riscv/target-attr-05.c new file mode 100644 index 00000000000..c75368dcebf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-05.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** foo: +** ... +** # tune = sifive-7-series +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long foo() __attribute__((target("cpu=sifive-u74;arch=rv64gc_zba"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-06.c b/gcc/testsuite/gcc.target/riscv/target-attr-06.c new file mode 100644 index 00000000000..369c95eeb54 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-06.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** foo: +** ... +** # tune = sifive-5-series +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long foo() __attribute__((target("cpu=sifive-u74;tune=sifive-5-series;arch=rv64gc_zba"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-07.c b/gcc/testsuite/gcc.target/riscv/target-attr-07.c new file mode 100644 index 00000000000..4ff81166a62 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-07.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** foo: +** ... +** # tune = sifive-5-series +** ... +*/ +long foo() __attribute__((target("tune=sifive-5-series"))); +long foo(long a, long b){ + return a + (b * 2); +} + +/* +** bar: +** ... +** sh1add\s*a0,a1,a0 +** ... +*/ +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-01.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-01.c new file mode 100644 index 00000000000..91cbcaac21d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-01.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target("arch=rv64gc_zba;;"))); /* { dg-error "malformed" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-02.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-02.c new file mode 100644 index 00000000000..0c838bb3ca7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-02.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target("cpu=xyz-cpu"))); /* { dg-error "unknown CPU" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-03.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-03.c new file mode 100644 index 00000000000..09702d1690a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-03.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target("tune=xyz-cpu"))); /* { dg-error "unknown TUNE" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-04.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-04.c new file mode 100644 index 00000000000..1d9a0ffdd88 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-04.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target(123))); /* { dg-error "argument not a string" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-05.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-05.c new file mode 100644 index 00000000000..24a81c5279b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-05.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target(""))); /* { dg-warning "empty string in attribute .target." } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-06.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-06.c new file mode 100644 index 00000000000..a0d65859d40 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-06.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target("arch=*x"))); /* { dg-error "must start with \\+ or rv" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-07.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-07.c new file mode 100644 index 00000000000..8aa82504dc1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-07.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + + +long foo() __attribute__((target("arch=+zbb_zba"))); /* { dg-error "extension 'zbb_zba' starts with 'z' but is unsupported standard extension" } */ +long foo(long a, long b){ + return a + (b * 2); +} + +long bar(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-08.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-08.c new file mode 100644 index 00000000000..68d211de887 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-08.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + +long foo() __attribute__((target("arch=rv64gc_zba;arch=rv64gc_zba"))); /* { dg-error "arch appears more than once" } */ +long foo(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-09.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-09.c new file mode 100644 index 00000000000..2b6e4982894 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-09.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + +long foo() __attribute__((target("cpu=sifive-u74;cpu=sifive-u74"))); /* { dg-error "cpu appears more than once" } */ +long foo(long a, long b){ + return a + (b * 2); +} diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-bad-10.c b/gcc/testsuite/gcc.target/riscv/target-attr-bad-10.c new file mode 100644 index 00000000000..00cefa03e41 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/target-attr-bad-10.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ + +long foo() __attribute__((target("tune=sifive-u74;tune=sifive-u74"))); /* { dg-error "tune appears more than once" } */ +long foo(long a, long b){ + return a + (b * 2); +}