From patchwork Wed Jul 19 15:15:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tamar Christina X-Patchwork-Id: 122680 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c923:0:b0:3e4:2afc:c1 with SMTP id j3csp2510211vqt; Wed, 19 Jul 2023 08:17:14 -0700 (PDT) X-Google-Smtp-Source: APBJJlHLPF6Lp5rHFmdQn/OCI+4O/3YiTtb7s3FI1eKeKGCVp3Z4dIF1Vtas1WIPG+xEGIH7Wv+m X-Received: by 2002:a17:906:c:b0:994:1956:2331 with SMTP id 12-20020a170906000c00b0099419562331mr2417136eja.13.1689779833932; Wed, 19 Jul 2023 08:17:13 -0700 (PDT) Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id p14-20020a17090628ce00b0095317ae767esi3187810ejd.46.2023.07.19.08.17.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jul 2023 08:17:13 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=IV+HtZ75; arc=fail (signature failed); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 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 DBFDE385703A for ; Wed, 19 Jul 2023 15:17:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DBFDE385703A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689779826; bh=rj4dZYiNdWGsOabXfZP3rz5KY2JYV/cBzKPSQ3Ygwno=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=IV+HtZ75uZ1MrcAKwHFoSuiWM8A5k9zCcKgyyOTMoLALr17SksQCtG7k1k20fiG+r CE5kgq6gjFQlyvmR5nI+rohBvrhVYegWLAkYe1RQ4L3/QjCsLc9g5XRZuXwa6zB7QS dGqnwtdop5OvBlK0TEFrhV+3iAyiKQ/crBmqUliE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04on2075.outbound.protection.outlook.com [40.107.6.75]) by sourceware.org (Postfix) with ESMTPS id EB1103858C33 for ; Wed, 19 Jul 2023 15:16:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EB1103858C33 Received: from DU2PR04CA0073.eurprd04.prod.outlook.com (2603:10a6:10:232::18) by AS8PR08MB6071.eurprd08.prod.outlook.com (2603:10a6:20b:29f::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6588.33; Wed, 19 Jul 2023 15:16:05 +0000 Received: from DBAEUR03FT050.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:232:cafe::c9) by DU2PR04CA0073.outlook.office365.com (2603:10a6:10:232::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6609.24 via Frontend Transport; Wed, 19 Jul 2023 15:16:04 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DBAEUR03FT050.mail.protection.outlook.com (100.127.142.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6588.34 via Frontend Transport; Wed, 19 Jul 2023 15:16:04 +0000 Received: ("Tessian outbound e1fdbe8a48d3:v145"); Wed, 19 Jul 2023 15:16:04 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 8126ea15ad39441d X-CR-MTA-TID: 64aa7808 Received: from ff5bf15ad153.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id A4264F23-3D54-4E5E-B7B4-CD4AA0052A38.1; Wed, 19 Jul 2023 15:15:58 +0000 Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id ff5bf15ad153.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 19 Jul 2023 15:15:58 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=cictuWzsCBNo7B6J2p0cLu2/nF8vS4wcCWgZoDNgfR8a6bR/B6obmd1Y6BpYcjE9rcbkFDEoDZml/nLqURtqvE/wzzvCvWIhTWAZK+wMbPS4inwzKybe6HEmfacwxWCsGqSg48yIqAIr1zxoFsCUo4IHdjNvTzAva/F/hSrSN1+YL0oKz+1jgc3XilBkRgs3Nz8GeNyI8gLcipLLMxnB+OAAaXovwysuM/o1JJl4GkGwDck8bqZ75doRtNk4eebBMdzfUsAlvJoCNAOJjYH557ru6q10RrDhH0pYT2T6qMUygYqAJUj0G7aD/OScIYA1CYXcFznF29ZKb+SsyahEAg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=rj4dZYiNdWGsOabXfZP3rz5KY2JYV/cBzKPSQ3Ygwno=; b=HVNz5DCjFO4OeLxV0UJSLebVf2LP4vVyzrUN0Yp9Hgbl7HpTKpec+joYBI6pocSItj5tzcBkWR7Ewtufa3N60vRYx3VNZhdX384WRtDyhQu+uemnVQKAc4eiZTo4ai4vEJkIiUnfZj8Q47g4bGCLSOVQ0u09QG3suoJCvqFVz/Bx//NENoqS8y5qfkUwBahNNtoOmia5cIPFFrbfeY4DxTRMoFDVwwL+iD51y5ZSGeQMeHE8CbqtWZje8OeAQ+OKkFww6M5Pjsb7Dfvy4v40YDX3aaryaQnhHCTApPdryMpaKGEkleHk1IWwQLo8rqj7s9Iyb6o0nrbphAMRmpPO2g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from AM0PR08MB5316.eurprd08.prod.outlook.com (2603:10a6:208:185::14) by DB3PR08MB8818.eurprd08.prod.outlook.com (2603:10a6:10:434::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6609.23; Wed, 19 Jul 2023 15:15:54 +0000 Received: from AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::1a75:e30c:4678:5fa3]) by AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::1a75:e30c:4678:5fa3%4]) with mapi id 15.20.6588.031; Wed, 19 Jul 2023 15:15:54 +0000 Date: Wed, 19 Jul 2023 16:15:50 +0100 To: gcc-patches@gcc.gnu.org Cc: nd@arm.com, jason@redhat.com, nathan@acm.org Subject: [PATCH 1/2][frontend] Add novector C++ pragma Message-ID: Content-Disposition: inline X-ClientProxiedBy: LO4P123CA0248.GBRP123.PROD.OUTLOOK.COM (2603:10a6:600:1a7::19) To AM0PR08MB5316.eurprd08.prod.outlook.com (2603:10a6:208:185::14) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: AM0PR08MB5316:EE_|DB3PR08MB8818:EE_|DBAEUR03FT050:EE_|AS8PR08MB6071:EE_ X-MS-Office365-Filtering-Correlation-Id: 241bd721-0dec-4ec2-0ffe-08db886b1209 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: pbMiJkI1q7xR3Lg4WYUv5uwDGuRTest7kxqp4nlfem1Z8X4hu5oFUaUoQnyLDWPH4qfb27+ESbDyyJYoAlW8fxczdmsEjqiMgKBZH9Dp6K6Av3vbQxOVQfuQJqwRjeoKiMIiSHZWnr48rDxf2eNrP79K7kIz5L1saIms+Sur0Y+UBC27LEGShRjdNz5qwZvU9U4M+8poRtFxe6Y6uZ2dMPTkETwGB1I8SIbIeG6yAq2mWf11i5GdzOBbjB9exfuD0HmgmLP5z/eJttIjWX5vqUtO2MSU4+ludR+qG18n/AmloViBXRKa2KV8YIvMQwDOPNEzKbNnXrZnamZZjoXC19E6nS7Txuq86w4lZcZYcP8FGfFFOPxdEZix6+735br1XA7FNiJO5zhBOxBP8+WX0FnJtpLCpaaVvfYvLRoipg+x3qJtAbk8jDQdJO0sRQhyMxCn6tVhLtqMzYChgHA9vs25t4vn6ygI9SxDr0q7LmR51O0RlL8erbCMxBNZY0KJX9JNoWLqvVxlKkGok44YwqXESZrXTj611L3yPY9hiDlWYnHl1BDVSTG0YtOkBfs6N86E2KZ7YMnLEhwCORegxlVp49tnpJQfuAA7OKeR9o4o2IHelWXmMX5e/a58+jhSj0KNR4EZoc+n958ZgSKt+g== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM0PR08MB5316.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(346002)(39860400002)(366004)(396003)(136003)(451199021)(478600001)(6506007)(4743002)(186003)(26005)(6666004)(44144004)(6486002)(33964004)(66556008)(6916009)(4326008)(66476007)(66946007)(83380400001)(2616005)(6512007)(38100700002)(30864003)(235185007)(5660300002)(41300700001)(44832011)(2906002)(316002)(8936002)(8676002)(86362001)(36756003)(4216001)(2700100001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR08MB8818 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DBAEUR03FT050.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: aec4cdb6-afd5-4c51-d2e0-08db886b0bc6 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: QEMi5I6n6ejQ/MXMVyZ3pTWAOE/4syP35O+yJ7HVU57nGjjzJG2+Cjh3dyxfKkHrzmXZPICmzCDq99VsF1XBJhq4nss9GT+9q1SWEQkDFvn+9d0HqpRqga4eePbhjPewy4hzDbWsqKKqA42vO6/fqLHtdZXrp0KCZvezgP27cUcNF37kSyAx9jQy1zHo9S8Pxt4ehWUZ8xVUARkNo1LKMfGmttDvTm79bmUSANukmSs3Zjo+5FCGKkyIqNCKXGqJ0ZVFjlQOgAxXB4frAXpZzN9pl7XqA7EQFSIlHcTeT+PYoiZQsLQQQrXbwloQzCLriGm4ZoK8qPpp+1DWN6/ug3HTFWTUhasMi6U9roMUuF49eKyNZ7uZfTl+jJdCC9f2bEEMlAreuUGdYbQe2gm6YKE5ZDG+HLCg8ROHOQNtSqiLdJXe8Fy54bbNiYJdI2gfk1040lyGcY7i8f4ZRyDMg6P5F+y8Gy+naxuJQiVR2ybTkw4xr2oEVg80VAEmkKfnVnnlv42kptos0bDTX5NSqFrTeTg4mJuf1+C29d8cSehTIbwfDfyc2a1RIDgngqQ7SEVsVpipeGS4YDqNFTFK2LPrFBStz+5CN1oO/9hp0mDwzFj10sT85Vu3cFNzcY4oUhQzj01frJQKuC6UCFxLnoXQ/nKrDRe0Oup8kaEe2gylGR5slryMcD4hFMilsx/9E5GPw8yZv7id2HKjpuYBjEYIGHWcCcTIAW+kcE/RNIlDU+bRZsv7HzdheXicT6D1mJ9oBBbkjcphg6wpBgZcm7/ks5aq4M4zXzIn7Se89YQ= X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230028)(4636009)(376002)(396003)(136003)(346002)(39860400002)(82310400008)(451199021)(36840700001)(40470700004)(46966006)(40480700001)(44832011)(186003)(86362001)(4743002)(336012)(33964004)(4326008)(70206006)(6916009)(44144004)(70586007)(478600001)(41300700001)(316002)(6512007)(6486002)(6666004)(8936002)(8676002)(40460700003)(235185007)(26005)(5660300002)(6506007)(2616005)(83380400001)(36860700001)(2906002)(36756003)(81166007)(82740400003)(356005)(30864003)(47076005)(4216001)(2700100001); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jul 2023 15:16:04.8362 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 241bd721-0dec-4ec2-0ffe-08db886b1209 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: DBAEUR03FT050.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB6071 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE, UNPARSEABLE_RELAY 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: Tamar Christina via Gcc-patches From: Tamar Christina Reply-To: Tamar Christina Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771862579234021335 X-GMAIL-MSGID: 1771862579234021335 Hi All, FORTRAN currently has a pragma NOVECTOR for indicating that vectorization should not be applied to a particular loop. ICC/ICX also has such a pragma for C and C++ called #pragma novector. As part of this patch series I need a way to easily turn off vectorization of particular loops, particularly for testsuite reasons. This patch proposes a #pragma GCC novector that does the same for C++ as gfortan does for FORTRAN and what ICX/ICX does for C++. I added only some basic tests here, but the next patch in the series uses this in the testsuite in about ~800 tests. Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/cp/ChangeLog: * cp-tree.def (RANGE_FOR_STMT): Update comment. * cp-tree.h (RANGE_FOR_NOVECTOR): New. (cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Add novector param. * init.cc (build_vec_init): Default novector to false. * method.cc (build_comparison_op): Likewise. * parser.cc (cp_parser_statement): Likewise. (cp_parser_for, cp_parser_c_for, cp_parser_range_for, cp_convert_range_for, cp_parser_iteration_statement, cp_parser_omp_for_loop, cp_parser_pragma): Support novector. (cp_parser_pragma_novector): New. * pt.cc (tsubst_expr): Likewise. * semantics.cc (finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Likewise. gcc/ChangeLog: * doc/extend.texi: Document it. gcc/testsuite/ChangeLog: * g++.dg/vect/vect.exp (support vect- prefix). * g++.dg/vect/vect-novector-pragma.cc: New test. --- inline copy of patch -- diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 0e66ca70e00caa1dc4beada1024ace32954e2aaf..c13c8ea98a523c4ef1c55a11e02d5da9db7e367e 100644 --- diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 0e66ca70e00caa1dc4beada1024ace32954e2aaf..c13c8ea98a523c4ef1c55a11e02d5da9db7e367e 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -305,8 +305,8 @@ DEFTREECODE (IF_STMT, "if_stmt", tcc_statement, 4) /* Used to represent a range-based `for' statement. The operands are RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, RANGE_FOR_SCOPE, - RANGE_FOR_UNROLL, and RANGE_FOR_INIT_STMT, respectively. Only used in - templates. */ + RANGE_FOR_UNROLL, RANGE_FOR_NOVECTOR and RANGE_FOR_INIT_STMT, + respectively. Only used in templates. */ DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 6) /* Used to represent an expression statement. Use `EXPR_STMT_EXPR' to diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8398223311194837441107cb335d497ff5f5ec1c..bece7bff1f01a23cfc94386fd3295a0be8c462fe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5377,6 +5377,7 @@ get_vec_init_expr (tree t) #define RANGE_FOR_UNROLL(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 4) #define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 5) #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE)) +#define RANGE_FOR_NOVECTOR(NODE) TREE_LANG_FLAG_5 (RANGE_FOR_STMT_CHECK (NODE)) /* STMT_EXPR accessor. */ #define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0) @@ -7286,7 +7287,7 @@ extern bool maybe_clone_body (tree); /* In parser.cc */ extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool, - unsigned short); + unsigned short, bool); extern void cp_convert_omp_range_for (tree &, vec *, tree &, tree &, tree &, tree &, tree &, tree &); extern void cp_finish_omp_range_for (tree, tree); @@ -7609,16 +7610,19 @@ extern void begin_else_clause (tree); extern void finish_else_clause (tree); extern void finish_if_stmt (tree); extern tree begin_while_stmt (void); -extern void finish_while_stmt_cond (tree, tree, bool, unsigned short); +extern void finish_while_stmt_cond (tree, tree, bool, unsigned short, + bool); extern void finish_while_stmt (tree); extern tree begin_do_stmt (void); extern void finish_do_body (tree); -extern void finish_do_stmt (tree, tree, bool, unsigned short); +extern void finish_do_stmt (tree, tree, bool, unsigned short, + bool); extern tree finish_return_stmt (tree); extern tree begin_for_scope (tree *); extern tree begin_for_stmt (tree, tree); extern void finish_init_stmt (tree); -extern void finish_for_cond (tree, tree, bool, unsigned short); +extern void finish_for_cond (tree, tree, bool, unsigned short, + bool); extern void finish_for_expr (tree, tree); extern void finish_for_stmt (tree); extern tree begin_range_for_stmt (tree, tree); diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index af6e30f511e142c7a594e742d128b2bf0aa8fb8d..5b735b27e6f5bc6b439ae64665902f4f1ca76f95 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -4846,7 +4846,7 @@ build_vec_init (tree base, tree maxindex, tree init, finish_init_stmt (for_stmt); finish_for_cond (build2 (GT_EXPR, boolean_type_node, iterator, build_int_cst (TREE_TYPE (iterator), -1)), - for_stmt, false, 0); + for_stmt, false, 0, false); /* We used to pass this decrement to finish_for_expr; now we add it to elt_init below so it's part of the same full-expression as the initialization, and thus happens before any potentially throwing diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 91cf943f11089c0e6bcbe8377daa4e016f956d56..fce49c796199c2c65cd70684e2942fea1b6b2ebd 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -1645,7 +1645,8 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) add_stmt (idx); finish_init_stmt (for_stmt); finish_for_cond (build2 (LE_EXPR, boolean_type_node, idx, - maxval), for_stmt, false, 0); + maxval), for_stmt, false, 0, + false); finish_for_expr (cp_build_unary_op (PREINCREMENT_EXPR, TARGET_EXPR_SLOT (idx), false, complain), diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index dd3665c8ccf48a8a0b1ba2c06400fe50999ea240..8776e8f4cf8266ee715c3e7f943602fdb1acaf79 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2324,15 +2324,15 @@ static tree cp_parser_selection_statement static tree cp_parser_condition (cp_parser *); static tree cp_parser_iteration_statement - (cp_parser *, bool *, bool, unsigned short); + (cp_parser *, bool *, bool, unsigned short, bool); static bool cp_parser_init_statement (cp_parser *, tree *decl); static tree cp_parser_for - (cp_parser *, bool, unsigned short); + (cp_parser *, bool, unsigned short, bool); static tree cp_parser_c_for - (cp_parser *, tree, tree, bool, unsigned short); + (cp_parser *, tree, tree, bool, unsigned short, bool); static tree cp_parser_range_for - (cp_parser *, tree, tree, tree, bool, unsigned short, bool); + (cp_parser *, tree, tree, tree, bool, unsigned short, bool, bool); static void do_range_for_auto_deduction (tree, tree, tree, unsigned int); static tree cp_parser_perform_range_for_lookup @@ -12414,7 +12414,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, case RID_DO: case RID_FOR: std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); - statement = cp_parser_iteration_statement (parser, if_p, false, 0); + statement = cp_parser_iteration_statement (parser, if_p, false, 0, + false); break; case RID_BREAK: @@ -13594,7 +13595,8 @@ cp_parser_condition (cp_parser* parser) not included. */ static tree -cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll) +cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll, + bool novector) { tree init, scope, decl; bool is_range_for; @@ -13624,14 +13626,14 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll) if (is_range_for) return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll, - false); + novector, false); else - return cp_parser_c_for (parser, scope, init, ivdep, unroll); + return cp_parser_c_for (parser, scope, init, ivdep, unroll, novector); } static tree cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { /* Normal for loop */ tree condition = NULL_TREE; @@ -13658,7 +13660,13 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, "% pragma"); condition = error_mark_node; } - finish_for_cond (condition, stmt, ivdep, unroll); + else if (novector) + { + cp_parser_error (parser, "missing loop condition in loop with " + "% pragma"); + condition = error_mark_node; + } + finish_for_cond (condition, stmt, ivdep, unroll, novector); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); @@ -13682,7 +13690,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, static tree cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, - bool ivdep, unsigned short unroll, bool is_omp) + bool ivdep, unsigned short unroll, bool novector, + bool is_omp) { tree stmt, range_expr; auto_vec bindings; @@ -13758,6 +13767,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, RANGE_FOR_IVDEP (stmt) = 1; if (unroll) RANGE_FOR_UNROLL (stmt) = build_int_cst (integer_type_node, unroll); + if (novector) + RANGE_FOR_NOVECTOR (stmt) = 1; finish_range_for_decl (stmt, range_decl, range_expr); if (!type_dependent_expression_p (range_expr) /* do_auto_deduction doesn't mess with template init-lists. */ @@ -13770,7 +13781,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, stmt = begin_for_stmt (scope, init); stmt = cp_convert_range_for (stmt, range_decl, range_expr, decomp_first_name, decomp_cnt, ivdep, - unroll); + unroll, novector); } return stmt; } @@ -13948,7 +13959,7 @@ warn_for_range_copy (tree decl, tree expr) tree cp_convert_range_for (tree statement, tree range_decl, tree range_expr, tree decomp_first_name, unsigned int decomp_cnt, - bool ivdep, unsigned short unroll) + bool ivdep, unsigned short unroll, bool novector) { tree begin, end; tree iter_type, begin_expr, end_expr; @@ -14008,7 +14019,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr, begin, ERROR_MARK, end, ERROR_MARK, NULL_TREE, NULL, tf_warning_or_error); - finish_for_cond (condition, statement, ivdep, unroll); + finish_for_cond (condition, statement, ivdep, unroll, novector); /* The new increment expression. */ expression = finish_unary_op_expr (input_location, @@ -14175,7 +14186,7 @@ cp_parser_range_for_member_function (tree range, tree identifier) static tree cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { cp_token *token; enum rid keyword; @@ -14209,7 +14220,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, parens.require_open (parser); /* Parse the condition. */ condition = cp_parser_condition (parser); - finish_while_stmt_cond (condition, statement, ivdep, unroll); + finish_while_stmt_cond (condition, statement, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); /* Parse the dependent statement. */ @@ -14244,7 +14255,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, /* Parse the expression. */ expression = cp_parser_expression (parser); /* We're done with the do-statement. */ - finish_do_stmt (expression, statement, ivdep, unroll); + finish_do_stmt (expression, statement, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); /* Look for the `;'. */ @@ -14258,7 +14269,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, matching_parens parens; parens.require_open (parser); - statement = cp_parser_for (parser, ivdep, unroll); + statement = cp_parser_for (parser, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); @@ -43815,7 +43826,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, cp_parser_require (parser, CPP_COLON, RT_COLON); init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, decl, - false, 0, true); + false, 0, false, true); cp_convert_omp_range_for (this_pre_body, for_block, decl, orig_decl, init, orig_init, @@ -49300,6 +49311,15 @@ cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok) return unroll; } +/* Parse a pragma GCC novector. */ + +static bool +cp_parser_pragma_novector (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return true; +} + /* Normal parsing of a pragma token. Here we can (and must) use the regular lexer. */ @@ -49605,58 +49625,73 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) break; case PRAGMA_IVDEP: + case PRAGMA_UNROLL: + case PRAGMA_NOVECTOR: { - if (context == pragma_external) + bool ivdep; + unsigned short unroll = 0; + bool novector = false; + const char *pragma_str; + + switch (id) { - error_at (pragma_tok->location, - "%<#pragma GCC ivdep%> must be inside a function"); + case PRAGMA_IVDEP: + pragma_str = "ivdep"; break; - } - const bool ivdep = cp_parser_pragma_ivdep (parser, pragma_tok); - unsigned short unroll; - cp_token *tok = cp_lexer_peek_token (the_parser->lexer); - if (tok->type == CPP_PRAGMA - && cp_parser_pragma_kind (tok) == PRAGMA_UNROLL) - { - tok = cp_lexer_consume_token (parser->lexer); - unroll = cp_parser_pragma_unroll (parser, tok); - tok = cp_lexer_peek_token (the_parser->lexer); - } - else - unroll = 0; - if (tok->type != CPP_KEYWORD - || (tok->keyword != RID_FOR - && tok->keyword != RID_WHILE - && tok->keyword != RID_DO)) - { - cp_parser_error (parser, "for, while or do statement expected"); - return false; - } - cp_parser_iteration_statement (parser, if_p, ivdep, unroll); - return true; - } + case PRAGMA_UNROLL: + pragma_str = "unroll"; + break; + case PRAGMA_NOVECTOR: + pragma_str = "novector"; + break; + default: + gcc_unreachable (); + } - case PRAGMA_UNROLL: - { if (context == pragma_external) { error_at (pragma_tok->location, - "%<#pragma GCC unroll%> must be inside a function"); + "%<#pragma GCC %s%> must be inside a function", + pragma_str); break; } - const unsigned short unroll - = cp_parser_pragma_unroll (parser, pragma_tok); - bool ivdep; - cp_token *tok = cp_lexer_peek_token (the_parser->lexer); - if (tok->type == CPP_PRAGMA - && cp_parser_pragma_kind (tok) == PRAGMA_IVDEP) + + cp_token *tok = pragma_tok; + + do { - tok = cp_lexer_consume_token (parser->lexer); - ivdep = cp_parser_pragma_ivdep (parser, tok); - tok = cp_lexer_peek_token (the_parser->lexer); + switch (cp_parser_pragma_kind (tok)) + { + case PRAGMA_IVDEP: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + ivdep = cp_parser_pragma_ivdep (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + case PRAGMA_UNROLL: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + unroll = cp_parser_pragma_unroll (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + case PRAGMA_NOVECTOR: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + novector = cp_parser_pragma_novector (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + default: + gcc_unreachable (); + } } - else - ivdep = false; + while (tok->type == CPP_PRAGMA); + if (tok->type != CPP_KEYWORD || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE @@ -49665,7 +49700,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) cp_parser_error (parser, "for, while or do statement expected"); return false; } - cp_parser_iteration_statement (parser, if_p, ivdep, unroll); + cp_parser_iteration_statement (parser, if_p, ivdep, unroll, novector); return true; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 2345a18becc1160b9d12f3d88cccb66c8917373c..7b0d01a90e3c4012ec603ebe04cbbb31a7dd1570 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19036,7 +19036,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) RECUR (FOR_INIT_STMT (t)); finish_init_stmt (stmt); tmp = RECUR (FOR_COND (t)); - finish_for_cond (tmp, stmt, false, 0); + finish_for_cond (tmp, stmt, false, 0, false); tmp = RECUR (FOR_EXPR (t)); finish_for_expr (tmp, stmt); { @@ -19073,6 +19073,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) { RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t); RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t); + RANGE_FOR_NOVECTOR (stmt) = RANGE_FOR_NOVECTOR (t); finish_range_for_decl (stmt, decl, expr); if (decomp_first && decl != error_mark_node) cp_finish_decomp (decl, decomp_first, decomp_cnt); @@ -19083,7 +19084,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0); stmt = cp_convert_range_for (stmt, decl, expr, decomp_first, decomp_cnt, - RANGE_FOR_IVDEP (t), unroll); + RANGE_FOR_IVDEP (t), unroll, + RANGE_FOR_NOVECTOR (t)); } bool prev = note_iteration_stmt_body_start (); @@ -19096,7 +19098,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case WHILE_STMT: stmt = begin_while_stmt (); tmp = RECUR (WHILE_COND (t)); - finish_while_stmt_cond (tmp, stmt, false, 0); + finish_while_stmt_cond (tmp, stmt, false, 0, false); { bool prev = note_iteration_stmt_body_start (); RECUR (WHILE_BODY (t)); @@ -19114,7 +19116,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) } finish_do_body (stmt); tmp = RECUR (DO_COND (t)); - finish_do_stmt (tmp, stmt, false, 0); + finish_do_stmt (tmp, stmt, false, 0, false); break; case IF_STMT: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8fb47fd179eb2af2e82bf31d188023e9b9d41de9..b79975109c22ebcfcb060b4f20f32f69f3c3c444 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -1148,7 +1148,7 @@ begin_while_stmt (void) void finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { cond = maybe_convert_cond (cond); finish_cond (&WHILE_COND (while_stmt), cond); @@ -1168,6 +1168,13 @@ finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR, + TREE_TYPE (WHILE_COND (while_stmt)), + WHILE_COND (while_stmt), + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt)); } @@ -1212,7 +1219,8 @@ finish_do_body (tree do_stmt) COND is as indicated. */ void -finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll) +finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll, + bool novector) { cond = maybe_convert_cond (cond); end_maybe_infinite_loop (cond); @@ -1229,6 +1237,10 @@ finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll) cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_no_vector_kind), + integer_zero_node); DO_COND (do_stmt) = cond; } @@ -1325,7 +1337,7 @@ finish_init_stmt (tree for_stmt) FOR_STMT. */ void -finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll) +finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll, bool novector) { cond = maybe_convert_cond (cond); finish_cond (&FOR_COND (for_stmt), cond); @@ -1345,6 +1357,13 @@ finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll) annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR, + TREE_TYPE (FOR_COND (for_stmt)), + FOR_COND (for_stmt), + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt)); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 3040a9bdea65d27f8d20572b4ed37375f5fe949b..baac6643d1abbf33d592e68aca49ac83e3c29188 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -24349,6 +24349,25 @@ void ignore_vec_dep (int *a, int k, int c, int m) @} @end smallexample +@cindex pragma GCC novector +@item #pragma GCC novector + +With this pragma, the programmer asserts that the following loop should be +prevented from executing concurrently with SIMD (single instruction multiple +data) instructions. + +For example, the compiler cannot vectorize the following loop with the pragma: + +@smallexample +void foo (int n, int *a, int *b, int *c) +@{ + int i, j; +#pragma GCC novector + for (i = 0; i < n; ++i) + a[i] = b[i] + c[i]; +@} +@end smallexample + @cindex pragma GCC unroll @var{n} @item #pragma GCC unroll @var{n} diff --git a/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc new file mode 100644 index 0000000000000000000000000000000000000000..cd5fb7ba9d4806f4d5e484ec68c707ea0e28ad7c --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc @@ -0,0 +1,68 @@ +/* { dg-skip-if "incorrect syntax for c++98" { *-*-* } { "-std=c++98" } { "" } } */ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +#include + +void f4 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f5 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector +#pragma GCC ivdep +#pragma GCC unroll 2 + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f6 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC ivdep +#pragma GCC novector +#pragma GCC unroll 2 + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f7 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC ivdep +#pragma GCC unroll 2 +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f8 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector + for (int x : b) + { + a[i] += x; + i++; + } +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */ diff --git a/gcc/testsuite/g++.dg/vect/vect.exp b/gcc/testsuite/g++.dg/vect/vect.exp index df273233f47a788024bbe61128eaa96b639cb3b8..fc77120a83173c65ad147e8bb7c29ac82f06bb6d 100644 --- a/gcc/testsuite/g++.dg/vect/vect.exp +++ b/gcc/testsuite/g++.dg/vect/vect.exp @@ -64,7 +64,7 @@ dg-init # Main loop. et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \ - $srcdir/$subdir/{pr,simd}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS + $srcdir/$subdir/{pr,simd,vect-}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \ $srcdir/$subdir/slp-pr*.{c,cc,S} ]] "" $VECT_SLP_CFLAGS --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -305,8 +305,8 @@ DEFTREECODE (IF_STMT, "if_stmt", tcc_statement, 4) /* Used to represent a range-based `for' statement. The operands are RANGE_FOR_DECL, RANGE_FOR_EXPR, RANGE_FOR_BODY, RANGE_FOR_SCOPE, - RANGE_FOR_UNROLL, and RANGE_FOR_INIT_STMT, respectively. Only used in - templates. */ + RANGE_FOR_UNROLL, RANGE_FOR_NOVECTOR and RANGE_FOR_INIT_STMT, + respectively. Only used in templates. */ DEFTREECODE (RANGE_FOR_STMT, "range_for_stmt", tcc_statement, 6) /* Used to represent an expression statement. Use `EXPR_STMT_EXPR' to diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8398223311194837441107cb335d497ff5f5ec1c..bece7bff1f01a23cfc94386fd3295a0be8c462fe 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5377,6 +5377,7 @@ get_vec_init_expr (tree t) #define RANGE_FOR_UNROLL(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 4) #define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 5) #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE)) +#define RANGE_FOR_NOVECTOR(NODE) TREE_LANG_FLAG_5 (RANGE_FOR_STMT_CHECK (NODE)) /* STMT_EXPR accessor. */ #define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0) @@ -7286,7 +7287,7 @@ extern bool maybe_clone_body (tree); /* In parser.cc */ extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool, - unsigned short); + unsigned short, bool); extern void cp_convert_omp_range_for (tree &, vec *, tree &, tree &, tree &, tree &, tree &, tree &); extern void cp_finish_omp_range_for (tree, tree); @@ -7609,16 +7610,19 @@ extern void begin_else_clause (tree); extern void finish_else_clause (tree); extern void finish_if_stmt (tree); extern tree begin_while_stmt (void); -extern void finish_while_stmt_cond (tree, tree, bool, unsigned short); +extern void finish_while_stmt_cond (tree, tree, bool, unsigned short, + bool); extern void finish_while_stmt (tree); extern tree begin_do_stmt (void); extern void finish_do_body (tree); -extern void finish_do_stmt (tree, tree, bool, unsigned short); +extern void finish_do_stmt (tree, tree, bool, unsigned short, + bool); extern tree finish_return_stmt (tree); extern tree begin_for_scope (tree *); extern tree begin_for_stmt (tree, tree); extern void finish_init_stmt (tree); -extern void finish_for_cond (tree, tree, bool, unsigned short); +extern void finish_for_cond (tree, tree, bool, unsigned short, + bool); extern void finish_for_expr (tree, tree); extern void finish_for_stmt (tree); extern tree begin_range_for_stmt (tree, tree); diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index af6e30f511e142c7a594e742d128b2bf0aa8fb8d..5b735b27e6f5bc6b439ae64665902f4f1ca76f95 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -4846,7 +4846,7 @@ build_vec_init (tree base, tree maxindex, tree init, finish_init_stmt (for_stmt); finish_for_cond (build2 (GT_EXPR, boolean_type_node, iterator, build_int_cst (TREE_TYPE (iterator), -1)), - for_stmt, false, 0); + for_stmt, false, 0, false); /* We used to pass this decrement to finish_for_expr; now we add it to elt_init below so it's part of the same full-expression as the initialization, and thus happens before any potentially throwing diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 91cf943f11089c0e6bcbe8377daa4e016f956d56..fce49c796199c2c65cd70684e2942fea1b6b2ebd 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -1645,7 +1645,8 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain) add_stmt (idx); finish_init_stmt (for_stmt); finish_for_cond (build2 (LE_EXPR, boolean_type_node, idx, - maxval), for_stmt, false, 0); + maxval), for_stmt, false, 0, + false); finish_for_expr (cp_build_unary_op (PREINCREMENT_EXPR, TARGET_EXPR_SLOT (idx), false, complain), diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index dd3665c8ccf48a8a0b1ba2c06400fe50999ea240..8776e8f4cf8266ee715c3e7f943602fdb1acaf79 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2324,15 +2324,15 @@ static tree cp_parser_selection_statement static tree cp_parser_condition (cp_parser *); static tree cp_parser_iteration_statement - (cp_parser *, bool *, bool, unsigned short); + (cp_parser *, bool *, bool, unsigned short, bool); static bool cp_parser_init_statement (cp_parser *, tree *decl); static tree cp_parser_for - (cp_parser *, bool, unsigned short); + (cp_parser *, bool, unsigned short, bool); static tree cp_parser_c_for - (cp_parser *, tree, tree, bool, unsigned short); + (cp_parser *, tree, tree, bool, unsigned short, bool); static tree cp_parser_range_for - (cp_parser *, tree, tree, tree, bool, unsigned short, bool); + (cp_parser *, tree, tree, tree, bool, unsigned short, bool, bool); static void do_range_for_auto_deduction (tree, tree, tree, unsigned int); static tree cp_parser_perform_range_for_lookup @@ -12414,7 +12414,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, case RID_DO: case RID_FOR: std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc); - statement = cp_parser_iteration_statement (parser, if_p, false, 0); + statement = cp_parser_iteration_statement (parser, if_p, false, 0, + false); break; case RID_BREAK: @@ -13594,7 +13595,8 @@ cp_parser_condition (cp_parser* parser) not included. */ static tree -cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll) +cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll, + bool novector) { tree init, scope, decl; bool is_range_for; @@ -13624,14 +13626,14 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll) if (is_range_for) return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll, - false); + novector, false); else - return cp_parser_c_for (parser, scope, init, ivdep, unroll); + return cp_parser_c_for (parser, scope, init, ivdep, unroll, novector); } static tree cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { /* Normal for loop */ tree condition = NULL_TREE; @@ -13658,7 +13660,13 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, "% pragma"); condition = error_mark_node; } - finish_for_cond (condition, stmt, ivdep, unroll); + else if (novector) + { + cp_parser_error (parser, "missing loop condition in loop with " + "% pragma"); + condition = error_mark_node; + } + finish_for_cond (condition, stmt, ivdep, unroll, novector); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); @@ -13682,7 +13690,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep, static tree cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, - bool ivdep, unsigned short unroll, bool is_omp) + bool ivdep, unsigned short unroll, bool novector, + bool is_omp) { tree stmt, range_expr; auto_vec bindings; @@ -13758,6 +13767,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, RANGE_FOR_IVDEP (stmt) = 1; if (unroll) RANGE_FOR_UNROLL (stmt) = build_int_cst (integer_type_node, unroll); + if (novector) + RANGE_FOR_NOVECTOR (stmt) = 1; finish_range_for_decl (stmt, range_decl, range_expr); if (!type_dependent_expression_p (range_expr) /* do_auto_deduction doesn't mess with template init-lists. */ @@ -13770,7 +13781,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, stmt = begin_for_stmt (scope, init); stmt = cp_convert_range_for (stmt, range_decl, range_expr, decomp_first_name, decomp_cnt, ivdep, - unroll); + unroll, novector); } return stmt; } @@ -13948,7 +13959,7 @@ warn_for_range_copy (tree decl, tree expr) tree cp_convert_range_for (tree statement, tree range_decl, tree range_expr, tree decomp_first_name, unsigned int decomp_cnt, - bool ivdep, unsigned short unroll) + bool ivdep, unsigned short unroll, bool novector) { tree begin, end; tree iter_type, begin_expr, end_expr; @@ -14008,7 +14019,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr, begin, ERROR_MARK, end, ERROR_MARK, NULL_TREE, NULL, tf_warning_or_error); - finish_for_cond (condition, statement, ivdep, unroll); + finish_for_cond (condition, statement, ivdep, unroll, novector); /* The new increment expression. */ expression = finish_unary_op_expr (input_location, @@ -14175,7 +14186,7 @@ cp_parser_range_for_member_function (tree range, tree identifier) static tree cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { cp_token *token; enum rid keyword; @@ -14209,7 +14220,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, parens.require_open (parser); /* Parse the condition. */ condition = cp_parser_condition (parser); - finish_while_stmt_cond (condition, statement, ivdep, unroll); + finish_while_stmt_cond (condition, statement, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); /* Parse the dependent statement. */ @@ -14244,7 +14255,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, /* Parse the expression. */ expression = cp_parser_expression (parser); /* We're done with the do-statement. */ - finish_do_stmt (expression, statement, ivdep, unroll); + finish_do_stmt (expression, statement, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); /* Look for the `;'. */ @@ -14258,7 +14269,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep, matching_parens parens; parens.require_open (parser); - statement = cp_parser_for (parser, ivdep, unroll); + statement = cp_parser_for (parser, ivdep, unroll, novector); /* Look for the `)'. */ parens.require_close (parser); @@ -43815,7 +43826,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, cp_parser_require (parser, CPP_COLON, RT_COLON); init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, decl, - false, 0, true); + false, 0, false, true); cp_convert_omp_range_for (this_pre_body, for_block, decl, orig_decl, init, orig_init, @@ -49300,6 +49311,15 @@ cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok) return unroll; } +/* Parse a pragma GCC novector. */ + +static bool +cp_parser_pragma_novector (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return true; +} + /* Normal parsing of a pragma token. Here we can (and must) use the regular lexer. */ @@ -49605,58 +49625,73 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) break; case PRAGMA_IVDEP: + case PRAGMA_UNROLL: + case PRAGMA_NOVECTOR: { - if (context == pragma_external) + bool ivdep; + unsigned short unroll = 0; + bool novector = false; + const char *pragma_str; + + switch (id) { - error_at (pragma_tok->location, - "%<#pragma GCC ivdep%> must be inside a function"); + case PRAGMA_IVDEP: + pragma_str = "ivdep"; break; - } - const bool ivdep = cp_parser_pragma_ivdep (parser, pragma_tok); - unsigned short unroll; - cp_token *tok = cp_lexer_peek_token (the_parser->lexer); - if (tok->type == CPP_PRAGMA - && cp_parser_pragma_kind (tok) == PRAGMA_UNROLL) - { - tok = cp_lexer_consume_token (parser->lexer); - unroll = cp_parser_pragma_unroll (parser, tok); - tok = cp_lexer_peek_token (the_parser->lexer); - } - else - unroll = 0; - if (tok->type != CPP_KEYWORD - || (tok->keyword != RID_FOR - && tok->keyword != RID_WHILE - && tok->keyword != RID_DO)) - { - cp_parser_error (parser, "for, while or do statement expected"); - return false; - } - cp_parser_iteration_statement (parser, if_p, ivdep, unroll); - return true; - } + case PRAGMA_UNROLL: + pragma_str = "unroll"; + break; + case PRAGMA_NOVECTOR: + pragma_str = "novector"; + break; + default: + gcc_unreachable (); + } - case PRAGMA_UNROLL: - { if (context == pragma_external) { error_at (pragma_tok->location, - "%<#pragma GCC unroll%> must be inside a function"); + "%<#pragma GCC %s%> must be inside a function", + pragma_str); break; } - const unsigned short unroll - = cp_parser_pragma_unroll (parser, pragma_tok); - bool ivdep; - cp_token *tok = cp_lexer_peek_token (the_parser->lexer); - if (tok->type == CPP_PRAGMA - && cp_parser_pragma_kind (tok) == PRAGMA_IVDEP) + + cp_token *tok = pragma_tok; + + do { - tok = cp_lexer_consume_token (parser->lexer); - ivdep = cp_parser_pragma_ivdep (parser, tok); - tok = cp_lexer_peek_token (the_parser->lexer); + switch (cp_parser_pragma_kind (tok)) + { + case PRAGMA_IVDEP: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + ivdep = cp_parser_pragma_ivdep (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + case PRAGMA_UNROLL: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + unroll = cp_parser_pragma_unroll (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + case PRAGMA_NOVECTOR: + { + if (tok != pragma_tok) + tok = cp_lexer_consume_token (parser->lexer); + novector = cp_parser_pragma_novector (parser, tok); + tok = cp_lexer_peek_token (the_parser->lexer); + break; + } + default: + gcc_unreachable (); + } } - else - ivdep = false; + while (tok->type == CPP_PRAGMA); + if (tok->type != CPP_KEYWORD || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE @@ -49665,7 +49700,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) cp_parser_error (parser, "for, while or do statement expected"); return false; } - cp_parser_iteration_statement (parser, if_p, ivdep, unroll); + cp_parser_iteration_statement (parser, if_p, ivdep, unroll, novector); return true; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 2345a18becc1160b9d12f3d88cccb66c8917373c..7b0d01a90e3c4012ec603ebe04cbbb31a7dd1570 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19036,7 +19036,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) RECUR (FOR_INIT_STMT (t)); finish_init_stmt (stmt); tmp = RECUR (FOR_COND (t)); - finish_for_cond (tmp, stmt, false, 0); + finish_for_cond (tmp, stmt, false, 0, false); tmp = RECUR (FOR_EXPR (t)); finish_for_expr (tmp, stmt); { @@ -19073,6 +19073,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) { RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t); RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t); + RANGE_FOR_NOVECTOR (stmt) = RANGE_FOR_NOVECTOR (t); finish_range_for_decl (stmt, decl, expr); if (decomp_first && decl != error_mark_node) cp_finish_decomp (decl, decomp_first, decomp_cnt); @@ -19083,7 +19084,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0); stmt = cp_convert_range_for (stmt, decl, expr, decomp_first, decomp_cnt, - RANGE_FOR_IVDEP (t), unroll); + RANGE_FOR_IVDEP (t), unroll, + RANGE_FOR_NOVECTOR (t)); } bool prev = note_iteration_stmt_body_start (); @@ -19096,7 +19098,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case WHILE_STMT: stmt = begin_while_stmt (); tmp = RECUR (WHILE_COND (t)); - finish_while_stmt_cond (tmp, stmt, false, 0); + finish_while_stmt_cond (tmp, stmt, false, 0, false); { bool prev = note_iteration_stmt_body_start (); RECUR (WHILE_BODY (t)); @@ -19114,7 +19116,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) } finish_do_body (stmt); tmp = RECUR (DO_COND (t)); - finish_do_stmt (tmp, stmt, false, 0); + finish_do_stmt (tmp, stmt, false, 0, false); break; case IF_STMT: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8fb47fd179eb2af2e82bf31d188023e9b9d41de9..b79975109c22ebcfcb060b4f20f32f69f3c3c444 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -1148,7 +1148,7 @@ begin_while_stmt (void) void finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep, - unsigned short unroll) + unsigned short unroll, bool novector) { cond = maybe_convert_cond (cond); finish_cond (&WHILE_COND (while_stmt), cond); @@ -1168,6 +1168,13 @@ finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR, + TREE_TYPE (WHILE_COND (while_stmt)), + WHILE_COND (while_stmt), + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt)); } @@ -1212,7 +1219,8 @@ finish_do_body (tree do_stmt) COND is as indicated. */ void -finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll) +finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll, + bool novector) { cond = maybe_convert_cond (cond); end_maybe_infinite_loop (cond); @@ -1229,6 +1237,10 @@ finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll) cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_no_vector_kind), + integer_zero_node); DO_COND (do_stmt) = cond; } @@ -1325,7 +1337,7 @@ finish_init_stmt (tree for_stmt) FOR_STMT. */ void -finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll) +finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll, bool novector) { cond = maybe_convert_cond (cond); finish_cond (&FOR_COND (for_stmt), cond); @@ -1345,6 +1357,13 @@ finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll) annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR, + TREE_TYPE (FOR_COND (for_stmt)), + FOR_COND (for_stmt), + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt)); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 3040a9bdea65d27f8d20572b4ed37375f5fe949b..baac6643d1abbf33d592e68aca49ac83e3c29188 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -24349,6 +24349,25 @@ void ignore_vec_dep (int *a, int k, int c, int m) @} @end smallexample +@cindex pragma GCC novector +@item #pragma GCC novector + +With this pragma, the programmer asserts that the following loop should be +prevented from executing concurrently with SIMD (single instruction multiple +data) instructions. + +For example, the compiler cannot vectorize the following loop with the pragma: + +@smallexample +void foo (int n, int *a, int *b, int *c) +@{ + int i, j; +#pragma GCC novector + for (i = 0; i < n; ++i) + a[i] = b[i] + c[i]; +@} +@end smallexample + @cindex pragma GCC unroll @var{n} @item #pragma GCC unroll @var{n} diff --git a/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc new file mode 100644 index 0000000000000000000000000000000000000000..cd5fb7ba9d4806f4d5e484ec68c707ea0e28ad7c --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc @@ -0,0 +1,68 @@ +/* { dg-skip-if "incorrect syntax for c++98" { *-*-* } { "-std=c++98" } { "" } } */ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +#include + +void f4 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f5 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector +#pragma GCC ivdep +#pragma GCC unroll 2 + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f6 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC ivdep +#pragma GCC novector +#pragma GCC unroll 2 + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f7 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC ivdep +#pragma GCC unroll 2 +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +void f8 (std::vector a, std::vector b, int n) +{ + int i = 0; +#pragma GCC novector + for (int x : b) + { + a[i] += x; + i++; + } +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */ diff --git a/gcc/testsuite/g++.dg/vect/vect.exp b/gcc/testsuite/g++.dg/vect/vect.exp index df273233f47a788024bbe61128eaa96b639cb3b8..fc77120a83173c65ad147e8bb7c29ac82f06bb6d 100644 --- a/gcc/testsuite/g++.dg/vect/vect.exp +++ b/gcc/testsuite/g++.dg/vect/vect.exp @@ -64,7 +64,7 @@ dg-init # Main loop. et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \ - $srcdir/$subdir/{pr,simd}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS + $srcdir/$subdir/{pr,simd,vect-}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \ $srcdir/$subdir/slp-pr*.{c,cc,S} ]] "" $VECT_SLP_CFLAGS From patchwork Wed Jul 19 15:16:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tamar Christina X-Patchwork-Id: 122681 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c923:0:b0:3e4:2afc:c1 with SMTP id j3csp2511144vqt; Wed, 19 Jul 2023 08:18:40 -0700 (PDT) X-Google-Smtp-Source: APBJJlEP5TeTVNiN+BJjPqqg0nasTWzFW1dwUpVo/puCybP5wfkYiQhim95p/KInA3ZwYp6h5tWa X-Received: by 2002:a17:907:7805:b0:994:4e9c:30cc with SMTP id la5-20020a170907780500b009944e9c30ccmr2729903ejc.39.1689779919668; Wed, 19 Jul 2023 08:18:39 -0700 (PDT) Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id d25-20020a170906345900b00988a13c6a90si2899399ejb.601.2023.07.19.08.18.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jul 2023 08:18:39 -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="axkWyn/G"; arc=fail (signature failed); 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 9A365385AFA4 for ; Wed, 19 Jul 2023 15:17:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9A365385AFA4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689779869; bh=vfUToh2Vx0IxNSNC9r28APc4Ed00wUEfK/Adndrb2HY=; h=Date:To:Cc:Subject:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=axkWyn/GOurP+V0Bm1R0Kgb6Fti2c4BhHeWEtuZPRmnw9imBUicEsPp5YjGR8idQF m9sBREPzuZhhXmI8AXc12bvjloGNQ1CNuaczVcZiYiJyfxsKhovT6Nkm7UhmfHg4j+ RXJMYQiqw8I8s15JYb+ThbKGNQmjzLsu+vbpkkTQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from EUR05-AM6-obe.outbound.protection.outlook.com (mail-am6eur05on2048.outbound.protection.outlook.com [40.107.22.48]) by sourceware.org (Postfix) with ESMTPS id D850A3858436 for ; Wed, 19 Jul 2023 15:16:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D850A3858436 Received: from FR0P281CA0222.DEUP281.PROD.OUTLOOK.COM (2603:10a6:d10:ac::18) by DBBPR08MB6137.eurprd08.prod.outlook.com (2603:10a6:10:20f::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6609.24; Wed, 19 Jul 2023 15:16:51 +0000 Received: from VI1EUR03FT063.eop-EUR03.prod.protection.outlook.com (2603:10a6:d10:ac:cafe::52) by FR0P281CA0222.outlook.office365.com (2603:10a6:d10:ac::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6609.24 via Frontend Transport; Wed, 19 Jul 2023 15:16:51 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VI1EUR03FT063.mail.protection.outlook.com (100.127.144.155) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6588.33 via Frontend Transport; Wed, 19 Jul 2023 15:16:51 +0000 Received: ("Tessian outbound e1fdbe8a48d3:v145"); Wed, 19 Jul 2023 15:16:50 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 427b961879549f9d X-CR-MTA-TID: 64aa7808 Received: from 85340478f82d.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id A7E3ACAF-E75E-4362-A8EE-20647B9FEB60.1; Wed, 19 Jul 2023 15:16:43 +0000 Received: from EUR05-AM6-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 85340478f82d.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 19 Jul 2023 15:16:43 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=VGCLLF4tZgVmzk0BEJhK8NHK0JIY9v0hGaCpuo8PMycYV5yA/b8/opHaMVheTkY1EXMFS84gFKReEEvuhiknoB1whaLyWWQvlqZkL/YWhWribxUE/ZlvMZWvWJBW1E5dZwKVMTFNODyk8/lDalMmm2mN9ycc4q1HTFSSio6Z477RmwV9WgK/D/qLeQumWuACmHMdDDSa/wwfRVMvK33pO7BFY6GyHF/bMCQtjQzMgjPbCcMm4MM8o0GmPF7BRZtNLrY7xIruoWor1pwFHIXhxR73Kh2nUsdE3YVcJq3x+qcZkhx28nh+ekc2xbkHiAv380U65yI2zfKKJRHqAZxm6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=vfUToh2Vx0IxNSNC9r28APc4Ed00wUEfK/Adndrb2HY=; b=n7iE6ABhRUqlFJOCq51Bhz6DCc67zcFn+Fhb/KqbNZ14aKY1Phm1RWuPYMt+RhJpjkW3RDZ6UxtCM2By9XvzM/HbG94jFWvA9fPqNrLLg8WAbfiUNcxVl8okl7ExIpOakAmwdtQIDn9yuat3+QC0Cuvcl5LWq+edxpTRzzVupzOFkFeY/roV3sgRTHZgQvlP7681JnAeqSxSeF5vRQp4npicVTkEKywggewZyxj+LYnFrez7m87EDJmFLgHh4x0E9ys1VU3e70ANCNKDAnAo6T7XRB6DzPS5oRJO+5ZNioDrqd0RLQLByqs2qE23VwpPyU6gfotcOiXvS6iV2ifIMg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from AM0PR08MB5316.eurprd08.prod.outlook.com (2603:10a6:208:185::14) by DB3PR08MB8818.eurprd08.prod.outlook.com (2603:10a6:10:434::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6609.23; Wed, 19 Jul 2023 15:16:41 +0000 Received: from AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::1a75:e30c:4678:5fa3]) by AM0PR08MB5316.eurprd08.prod.outlook.com ([fe80::1a75:e30c:4678:5fa3%4]) with mapi id 15.20.6588.031; Wed, 19 Jul 2023 15:16:41 +0000 Date: Wed, 19 Jul 2023 16:16:34 +0100 To: gcc-patches@gcc.gnu.org Cc: nd@arm.com, joseph@codesourcery.com Subject: [PATCH 2/2][frontend]: Add novector C pragma Message-ID: Content-Disposition: inline In-Reply-To: X-ClientProxiedBy: SA0PR11CA0160.namprd11.prod.outlook.com (2603:10b6:806:1bb::15) To AM0PR08MB5316.eurprd08.prod.outlook.com (2603:10a6:208:185::14) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: AM0PR08MB5316:EE_|DB3PR08MB8818:EE_|VI1EUR03FT063:EE_|DBBPR08MB6137:EE_ X-MS-Office365-Filtering-Correlation-Id: 6d92ab40-cf8d-4d33-d25c-08db886b2dc0 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: lz1qxNTOy9QRuHD2TE2ThCffTA/mIMSaoTY67NjmcxlbqktcpaIjEw/FV8iVmm7VsdY9FjQSa/EaarnVmkhV6MltZMasv9NZDHMabGMLahWwOzIMraj1lsKKNeXDd52xm09mHMKlLDNAJeXiTsLM0dFJucJ3/dWdbx8Fl2QO92ZMAZKs8KR9N/QOrLOTUhpopBxuvaUUsoRoNC9hvpu3aYOCy6bYcwGklNv2ugTWX0lm6iJxUq6f4XJHxLOiUlCFqKsjpnoNU3rBban+nI3U+tGP3aLBYplOEaYeigYOFLUgHR64sDhl0AvkhqEKRmGkhoFT1OY5cKVY+uZT2TQP2cF/cTxNJEfwwjci+CRHdxQ5a63N4WmbO0CzSwvu7U/6r0bC88jR9I0qrEj8a6o3HIeLpwYQsJB171FKEXLz036KIQ3qzHdYlMmosxZDW/FkUKUwMJAdpbDWQTHqzFPtqJLWF7Zlab9yOYu/jS+NaltbS4HFL1UtJuA12WMkPIChHLmQrxvN6QPPbXOMkubJCkKVW6IUMwdxCbwTBhOG0y7B5gUz9CSY8Rq94mpZsnBLVRtzSSq9RnMU7crq0brcLi14TCpEIw6bUJBr4M0QfntAec+rd+gPYwlrlWxAyflX X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AM0PR08MB5316.eurprd08.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230028)(4636009)(376002)(346002)(39860400002)(366004)(396003)(136003)(451199021)(478600001)(6506007)(4743002)(186003)(26005)(6666004)(44144004)(6486002)(33964004)(66556008)(6916009)(4326008)(66476007)(66946007)(83380400001)(84970400001)(2616005)(6512007)(38100700002)(30864003)(235185007)(5660300002)(41300700001)(44832011)(2906002)(316002)(8936002)(8676002)(86362001)(36756003)(67856001)(2700100001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR08MB8818 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VI1EUR03FT063.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 8131349e-6b75-4855-6235-08db886b27a5 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sUVn1FoVbwNAvjls1XjxOOEoeFSnILc2pYVYupUqjQky0NK5/magrOpS45RuOB2srNfNGVWlncObhSGlslJnLesoCMU2iZzYbDizJwi9ZNxqBanrx+FTlTPuZZi/P1j288nZNsrch9eO1eJ3RRwwIvbU+AMzhanp4exGh7/pXSwNBDkAu4zPR/PVW9s/I8GclOS85+BxekQcRUGyNknTyh8lKxif5OfnZyODxUvqkuLvsrM3dhZNkLrdrL3Mj5rCAGzm0DH9+wCC70byz8mxXebEzIkhC4mznlT39NtcBT14B7ICgdVrHUjBvszgSh7Q1roFXQx5rc+Rd7PAokq5K9jyQznBFqbSfD/yKzgEKuV5WXKYllcQfSJFWhhG7wE4aYu36ajKlp2F7Vl9RzmFzv9+3CSAATl4601faoSzZLoeiFplgoYzAjruASbGLvHzZ29yEcOEkHrwSo3v09jFX66Dwi0k2PGBEYwR1JZb8gu/EhQ5QN5z6D5VcgNDqGvK+Y4fx/z+SDvG/uj29hoKybLra0WUrQjShDNtYKDMnoOgjgkNXeoNeVj0f+iR4wQ+q4xlJ+WQub6Rn/v/vnrNsIaFuvGye03va1Km+45qHy1aVGDqsAStogLmwGJ8aS9dB8QxvV9NFtr/XXdOc8FrhC/hUvBsDiA4inMi2P68eNKyxd/WDxjUjdfrhW9pYLvyvO6nckwqQitA9m1J2Wv1tfxQ22RzMrmNgTy0YopMpjMFGfBt/7KkfcQyrNR84fWfivJiCGmqicIvwoIBXJhNPB8vYEos1iW2SBRzrTZIluc= X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230028)(4636009)(396003)(376002)(136003)(346002)(39860400002)(82310400008)(451199021)(40470700004)(36840700001)(46966006)(2906002)(30864003)(40460700003)(478600001)(40480700001)(41300700001)(44832011)(8936002)(8676002)(5660300002)(235185007)(70206006)(70586007)(6916009)(4326008)(316002)(82740400003)(81166007)(84970400001)(107886003)(44144004)(33964004)(2616005)(36756003)(86362001)(36860700001)(47076005)(336012)(186003)(26005)(6506007)(356005)(4743002)(6486002)(83380400001)(6512007)(6666004)(2700100001)(67856001); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jul 2023 15:16:51.0109 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 6d92ab40-cf8d-4d33-d25c-08db886b2dc0 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: VI1EUR03FT063.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB6137 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE, UNPARSEABLE_RELAY 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: Tamar Christina via Gcc-patches From: Tamar Christina Reply-To: Tamar Christina Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771862669157888011 X-GMAIL-MSGID: 1771862669157888011 Hi All, FORTRAN currently has a pragma NOVECTOR for indicating that vectorization should not be applied to a particular loop. ICC/ICX also has such a pragma for C and C++ called #pragma novector. As part of this patch series I need a way to easily turn off vectorization of particular loops, particularly for testsuite reasons. This patch proposes a #pragma GCC novector that does the same for C as gfortan does for FORTRAN and what ICX/ICX does for C. I added only some basic tests here, but the next patch in the series uses this in the testsuite in about ~800 tests. Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. Ok for master? Thanks, Tamar gcc/c-family/ChangeLog: * c-pragma.h (enum pragma_kind): Add PRAGMA_NOVECTOR. * c-pragma.cc (init_pragma): Use it. gcc/c/ChangeLog: * c-parser.cc (c_parser_while_statement, c_parser_do_statement, c_parser_for_statement, c_parser_statement_after_labels, c_parse_pragma_novector, c_parser_pragma): Wire through novector and default to false. gcc/testsuite/ChangeLog: * gcc.dg/vect/vect-novector-pragma.c: New test. --- inline copy of patch -- diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 9cc95ab3ee376628dbef2485b84e6008210fa8fc..99cf2e8bd1c05537c198470f1aaa0a5a9da4e576 100644 --- diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 9cc95ab3ee376628dbef2485b84e6008210fa8fc..99cf2e8bd1c05537c198470f1aaa0a5a9da4e576 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -87,6 +87,7 @@ enum pragma_kind { PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, PRAGMA_UNROLL, + PRAGMA_NOVECTOR, PRAGMA_FIRST_EXTERNAL }; diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 0d2b333cebbed32423d5dc6fd2a3ac0ce0bf8b94..848a850b8e123ff1c6ae1ec4b7f8ccbd599b1a88 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -1862,6 +1862,10 @@ init_pragma (void) cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL, false, false); + if (!flag_preprocess_only) + cpp_register_deferred_pragma (parse_in, "GCC", "novector", PRAGMA_NOVECTOR, + false, false); + #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); #else diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 24a6eb6e4596f32c477e3f1c3f98b9792f7bc92c..4c64d898cddac437958ce20c5603b88a05a99093 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1572,9 +1572,11 @@ static tree c_parser_c99_block_statement (c_parser *, bool *, location_t * = NULL); static void c_parser_if_statement (c_parser *, bool *, vec *); static void c_parser_switch_statement (c_parser *, bool *); -static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *); -static void c_parser_do_statement (c_parser *, bool, unsigned short); -static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *); +static void c_parser_while_statement (c_parser *, bool, unsigned short, bool, + bool *); +static void c_parser_do_statement (c_parser *, bool, unsigned short, bool); +static void c_parser_for_statement (c_parser *, bool, unsigned short, bool, + bool *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -6644,13 +6646,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, c_parser_switch_statement (parser, if_p); break; case RID_WHILE: - c_parser_while_statement (parser, false, 0, if_p); + c_parser_while_statement (parser, false, 0, false, if_p); break; case RID_DO: - c_parser_do_statement (parser, false, 0); + c_parser_do_statement (parser, false, 0, false); break; case RID_FOR: - c_parser_for_statement (parser, false, 0, if_p); + c_parser_for_statement (parser, false, 0, false, if_p); break; case RID_GOTO: c_parser_consume_token (parser); @@ -7146,7 +7148,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) static void c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, body; unsigned char save_in_statement; @@ -7168,6 +7170,11 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); save_in_statement = in_statement; in_statement = IN_ITERATION_STMT; @@ -7199,7 +7206,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, */ static void -c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) +c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool novector) { tree block, cond, body; unsigned char save_in_statement; @@ -7228,6 +7236,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); @@ -7296,7 +7309,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) static void c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, incr, body; unsigned char save_in_statement; @@ -7430,6 +7443,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, "with % pragma"); cond = error_mark_node; } + else if (novector) + { + c_parser_error (parser, "missing loop condition in loop " + "with % pragma"); + cond = error_mark_node; + } else { c_parser_consume_token (parser); @@ -7452,6 +7471,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -13037,6 +13061,16 @@ c_parse_pragma_ivdep (c_parser *parser) return true; } +/* Parse a pragma GCC novector. */ + +static bool +c_parse_pragma_novector (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + return true; +} + /* Parse a pragma GCC unroll. */ static unsigned short @@ -13261,38 +13295,50 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_ORDERED: return c_parser_omp_ordered (parser, context, if_p); + case PRAGMA_NOVECTOR: + case PRAGMA_UNROLL: case PRAGMA_IVDEP: { - const bool ivdep = c_parse_pragma_ivdep (parser); - unsigned short unroll; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL) - unroll = c_parser_pragma_unroll (parser); - else - unroll = 0; - if (!c_parser_next_token_is_keyword (parser, RID_FOR) - && !c_parser_next_token_is_keyword (parser, RID_WHILE) - && !c_parser_next_token_is_keyword (parser, RID_DO)) + bool novector = false; + unsigned short unroll = 0; + bool ivdep = false; + + switch (id) { - c_parser_error (parser, "for, while or do statement expected"); - return false; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + break; + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + break; + default: + gcc_unreachable (); } - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); - else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); - else - c_parser_do_statement (parser, ivdep, unroll); - } - return true; - case PRAGMA_UNROLL: - { - unsigned short unroll = c_parser_pragma_unroll (parser); - bool ivdep; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP) - ivdep = c_parse_pragma_ivdep (parser); - else - ivdep = false; + c_token *tok = c_parser_peek_token (parser); + while (tok->type == CPP_PRAGMA) + { + switch (tok->pragma_kind) + { + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + tok = c_parser_peek_token (parser); + break; + default: + gcc_unreachable (); + } + } if (!c_parser_next_token_is_keyword (parser, RID_FOR) && !c_parser_next_token_is_keyword (parser, RID_WHILE) && !c_parser_next_token_is_keyword (parser, RID_DO)) @@ -13301,11 +13347,11 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) return false; } if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); + c_parser_for_statement (parser, ivdep, unroll, novector, if_p); else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); + c_parser_while_statement (parser, ivdep, unroll, novector, if_p); else - c_parser_do_statement (parser, ivdep, unroll); + c_parser_do_statement (parser, ivdep, unroll, novector); } return true; diff --git a/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c new file mode 100644 index 0000000000000000000000000000000000000000..3c0b8f5d2acbd276280785e8d0cbe1f7cd650266 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +void f1 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f2 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector +#pragma GCC ivdep +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f3 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC novector +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f4 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC unroll 2 +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f5 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + do + { + a[i] += b[i]; + i++; + } + while (i < (n & -8)); +} + +void f6 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */ --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -87,6 +87,7 @@ enum pragma_kind { PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, PRAGMA_UNROLL, + PRAGMA_NOVECTOR, PRAGMA_FIRST_EXTERNAL }; diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 0d2b333cebbed32423d5dc6fd2a3ac0ce0bf8b94..848a850b8e123ff1c6ae1ec4b7f8ccbd599b1a88 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -1862,6 +1862,10 @@ init_pragma (void) cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL, false, false); + if (!flag_preprocess_only) + cpp_register_deferred_pragma (parse_in, "GCC", "novector", PRAGMA_NOVECTOR, + false, false); + #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); #else diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 24a6eb6e4596f32c477e3f1c3f98b9792f7bc92c..4c64d898cddac437958ce20c5603b88a05a99093 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1572,9 +1572,11 @@ static tree c_parser_c99_block_statement (c_parser *, bool *, location_t * = NULL); static void c_parser_if_statement (c_parser *, bool *, vec *); static void c_parser_switch_statement (c_parser *, bool *); -static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *); -static void c_parser_do_statement (c_parser *, bool, unsigned short); -static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *); +static void c_parser_while_statement (c_parser *, bool, unsigned short, bool, + bool *); +static void c_parser_do_statement (c_parser *, bool, unsigned short, bool); +static void c_parser_for_statement (c_parser *, bool, unsigned short, bool, + bool *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -6644,13 +6646,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p, c_parser_switch_statement (parser, if_p); break; case RID_WHILE: - c_parser_while_statement (parser, false, 0, if_p); + c_parser_while_statement (parser, false, 0, false, if_p); break; case RID_DO: - c_parser_do_statement (parser, false, 0); + c_parser_do_statement (parser, false, 0, false); break; case RID_FOR: - c_parser_for_statement (parser, false, 0, if_p); + c_parser_for_statement (parser, false, 0, false, if_p); break; case RID_GOTO: c_parser_consume_token (parser); @@ -7146,7 +7148,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) static void c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, body; unsigned char save_in_statement; @@ -7168,6 +7170,11 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); save_in_statement = in_statement; in_statement = IN_ITERATION_STMT; @@ -7199,7 +7206,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll, */ static void -c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) +c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll, + bool novector) { tree block, cond, body; unsigned char save_in_statement; @@ -7228,6 +7236,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); @@ -7296,7 +7309,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll) static void c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, - bool *if_p) + bool novector, bool *if_p) { tree block, cond, incr, body; unsigned char save_in_statement; @@ -7430,6 +7443,12 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, "with % pragma"); cond = error_mark_node; } + else if (novector) + { + c_parser_error (parser, "missing loop condition in loop " + "with % pragma"); + cond = error_mark_node; + } else { c_parser_consume_token (parser); @@ -7452,6 +7471,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, unroll)); + if (novector && cond != error_mark_node) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_no_vector_kind), + integer_zero_node); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -13037,6 +13061,16 @@ c_parse_pragma_ivdep (c_parser *parser) return true; } +/* Parse a pragma GCC novector. */ + +static bool +c_parse_pragma_novector (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + return true; +} + /* Parse a pragma GCC unroll. */ static unsigned short @@ -13261,38 +13295,50 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_ORDERED: return c_parser_omp_ordered (parser, context, if_p); + case PRAGMA_NOVECTOR: + case PRAGMA_UNROLL: case PRAGMA_IVDEP: { - const bool ivdep = c_parse_pragma_ivdep (parser); - unsigned short unroll; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL) - unroll = c_parser_pragma_unroll (parser); - else - unroll = 0; - if (!c_parser_next_token_is_keyword (parser, RID_FOR) - && !c_parser_next_token_is_keyword (parser, RID_WHILE) - && !c_parser_next_token_is_keyword (parser, RID_DO)) + bool novector = false; + unsigned short unroll = 0; + bool ivdep = false; + + switch (id) { - c_parser_error (parser, "for, while or do statement expected"); - return false; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + break; + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + break; + default: + gcc_unreachable (); } - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); - else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); - else - c_parser_do_statement (parser, ivdep, unroll); - } - return true; - case PRAGMA_UNROLL: - { - unsigned short unroll = c_parser_pragma_unroll (parser); - bool ivdep; - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP) - ivdep = c_parse_pragma_ivdep (parser); - else - ivdep = false; + c_token *tok = c_parser_peek_token (parser); + while (tok->type == CPP_PRAGMA) + { + switch (tok->pragma_kind) + { + case PRAGMA_IVDEP: + ivdep = c_parse_pragma_ivdep (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_UNROLL: + unroll = c_parser_pragma_unroll (parser); + tok = c_parser_peek_token (parser); + break; + case PRAGMA_NOVECTOR: + novector = c_parse_pragma_novector (parser); + tok = c_parser_peek_token (parser); + break; + default: + gcc_unreachable (); + } + } if (!c_parser_next_token_is_keyword (parser, RID_FOR) && !c_parser_next_token_is_keyword (parser, RID_WHILE) && !c_parser_next_token_is_keyword (parser, RID_DO)) @@ -13301,11 +13347,11 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) return false; } if (c_parser_next_token_is_keyword (parser, RID_FOR)) - c_parser_for_statement (parser, ivdep, unroll, if_p); + c_parser_for_statement (parser, ivdep, unroll, novector, if_p); else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) - c_parser_while_statement (parser, ivdep, unroll, if_p); + c_parser_while_statement (parser, ivdep, unroll, novector, if_p); else - c_parser_do_statement (parser, ivdep, unroll); + c_parser_do_statement (parser, ivdep, unroll, novector); } return true; diff --git a/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c new file mode 100644 index 0000000000000000000000000000000000000000..3c0b8f5d2acbd276280785e8d0cbe1f7cd650266 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +void f1 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f2 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC novector +#pragma GCC ivdep +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f3 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC novector +#pragma GCC unroll 2 + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f4 (int * restrict a, int * restrict b, int n) +{ +#pragma GCC ivdep +#pragma GCC unroll 2 +#pragma GCC novector + for (int i = 0; i < (n & -8); i++) + a[i] += b[i]; +} + +void f5 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + do + { + a[i] += b[i]; + i++; + } + while (i < (n & -8)); +} + +void f6 (int * restrict a, int * restrict b, int n) +{ + int i = 0; +#pragma GCC novector + while (i < (n & -8)) + { + a[i] += b[i]; + i++; + } +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */