From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rj4dZYiNdWGsOabXfZP3rz5KY2JYV/cBzKPSQ3Ygwno=; b=M077AKYIVoFuV5NaglbS5Jy9E6YNLClDL9yOQooTGwp2jm7K4mdz557DUJ8eG+HuGOJvLVyf33jJZqC0O6J638SGDY/16niNsSVBzvCQ3z69L6UxUT2PQhoLBk44NQAqox70ZyMTGIa22kn978+O1FCIHvpBQNmesacXU1Yug7U= 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 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rj4dZYiNdWGsOabXfZP3rz5KY2JYV/cBzKPSQ3Ygwno=; b=M077AKYIVoFuV5NaglbS5Jy9E6YNLClDL9yOQooTGwp2jm7K4mdz557DUJ8eG+HuGOJvLVyf33jJZqC0O6J638SGDY/16niNsSVBzvCQ3z69L6UxUT2PQhoLBk44NQAqox70ZyMTGIa22kn978+O1FCIHvpBQNmesacXU1Yug7U= 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 From: Tamar Christina 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-Type: multipart/mixed; boundary="gE/BQhFQIOvISyKb" 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 List-Id: --gE/BQhFQIOvISyKb Content-Type: text/plain; charset=utf-8 Content-Disposition: inline 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 --- 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 -- --gE/BQhFQIOvISyKb Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="rb17578.patch" 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 --gE/BQhFQIOvISyKb--