From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 7AED73858D35 for ; Wed, 26 Jul 2023 20:52:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7AED73858D35 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1690404751; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0p4LJX6hFLI6auz2A9txTbGknVuVy5ve5FsKy3W4BtE=; b=EgWX3lxjuQ287txKm79ujDWekC/MIwNeFcvSfLlhbPPclUXGyROxNPcytACBLHZ13iPew7 xbHBGpQooO5jwEgue7JumVnwXp5vTy5GlxNmxfJkplCqwZfKdfFx4grNm1m1ZNOPmDHdyf DPZRHcD6LXJs0dOojJS5JNyfJjft4+c= Received: from mail-ua1-f71.google.com (mail-ua1-f71.google.com [209.85.222.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-385-1LqUJMlfO-y29xttAV-ZQw-1; Wed, 26 Jul 2023 16:52:30 -0400 X-MC-Unique: 1LqUJMlfO-y29xttAV-ZQw-1 Received: by mail-ua1-f71.google.com with SMTP id a1e0cc1a2514c-791e11ad8a9so83667241.0 for ; Wed, 26 Jul 2023 13:52:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1690404749; x=1691009549; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0p4LJX6hFLI6auz2A9txTbGknVuVy5ve5FsKy3W4BtE=; b=MLSmjJiZlfBuy5J4eLLy7iqC8ZmX6H5DOWHjAOiTNbs/EM+JJ9EfdkL8ilqSYq0fBH FZburAYZEeadNHrlbS7yuIsE/AyPFrN8kuc9XZerp7zEZlC1jvXZ/aHkBF3xH6cgKkEX LSlFnqiSS62/Dzlj7ZZaONphUH67Bm2hHlXLGy4YT3TMQ0GR509c2UCh0YyXPrBvSLjj ZIUnUZTvt66s6fdBWim+91h9fmH/2311ci/jElreoTAIXhK1+YmIVluJlg2b6JOEnlTZ cM86r6VYvRoLvlvVDthAaPfHk8hrVtArIZyU0EtmRYGHiQ1dpYLeSmp8QSWAZf86cjZn IEnQ== X-Gm-Message-State: ABy/qLbR84dzonakc2auN8Qo2/LmCJrh7cCMZrns6/fWIt5mrwBxF7xG ksofXZk0Apr+TWqViUzZfpUy4JIX4PM9hyMTYITZY1R4Sb4NSW2rTggALRf3doObe6eg49sl7Cz mkTTOCzaBWI9jrwkIeA== X-Received: by 2002:a05:6102:1d0:b0:43d:6660:581b with SMTP id s16-20020a05610201d000b0043d6660581bmr290003vsq.5.1690404749297; Wed, 26 Jul 2023 13:52:29 -0700 (PDT) X-Google-Smtp-Source: APBJJlHj7VL4ihfunH2Yv5tkyf4HQz8DSb1cWEpvpJVWa5qji72cQc0J/l2C9TJ1T5RQgZy9El772g== X-Received: by 2002:a05:6102:1d0:b0:43d:6660:581b with SMTP id s16-20020a05610201d000b0043d6660581bmr289972vsq.5.1690404748796; Wed, 26 Jul 2023 13:52:28 -0700 (PDT) Received: from [192.168.1.108] (130-44-146-16.s12558.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.146.16]) by smtp.gmail.com with ESMTPSA id s3-20020a0cdc03000000b0063007ccaf42sm3307702qvk.57.2023.07.26.13.52.27 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 26 Jul 2023 13:52:28 -0700 (PDT) Message-ID: Date: Wed, 26 Jul 2023 16:52:26 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0 Subject: Re: [PATCH 1/2][frontend] Add novector C++ pragma To: Tamar Christina , "gcc-patches@gcc.gnu.org" Cc: nd , "nathan@acm.org" References: <1437ed35-e278-4eea-eb50-fa918af927bd@redhat.com> From: Jason Merrill In-Reply-To: X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_LOTSOFHASH,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 7/26/23 15:32, Tamar Christina wrote: >>> + >>> + 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 (); >> >> This unreachable seems to assert that if a pragma follows one of these >> pragmas, it must be another one of these pragmas? That seems wrong; >> instead of hitting gcc_unreachable() in that case we should fall through to the >> diagnostic below. >> > > Ah, good should. Since it has to exit two levels I had to introduce a bool > for controlling the loop iterations. New patch below. > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > Ok for master? OK. > Thanks, > Tamar > > gcc/cp/ChangeLog: > > * 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.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..092f991d7a1b6aab8482d50848fb9fb96c377509 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,7 @@ 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); > + finish_for_cond (condition, stmt, ivdep, unroll, novector); > /* Look for the `;'. */ > cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); > > @@ -13682,7 +13684,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 +13761,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 +13775,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 +13953,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 +14013,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 +14180,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 +14214,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 +14249,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 +14263,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 +43820,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 +49305,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 +49619,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; > + bool has_more = true; > + do > { > - tok = cp_lexer_consume_token (parser->lexer); > - ivdep = cp_parser_pragma_ivdep (parser, tok); > + 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); > + break; > + } > + case PRAGMA_UNROLL: > + { > + if (tok != pragma_tok) > + tok = cp_lexer_consume_token (parser->lexer); > + unroll = cp_parser_pragma_unroll (parser, tok); > + break; > + } > + case PRAGMA_NOVECTOR: > + { > + if (tok != pragma_tok) > + tok = cp_lexer_consume_token (parser->lexer); > + novector = cp_parser_pragma_novector (parser, tok); > + break; > + } > + default: > + has_more = false; > + break; > + } > tok = cp_lexer_peek_token (the_parser->lexer); > + has_more = has_more && tok->type == CPP_PRAGMA; > } > - else > - ivdep = false; > + while (has_more); > + > if (tok->type != CPP_KEYWORD > || (tok->keyword != RID_FOR > && tok->keyword != RID_WHILE > @@ -49665,7 +49694,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..8c6ff22fcaabaa97516be72b77acbd44df86b1d2 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc > @@ -0,0 +1,69 @@ > +/* { 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++; > + } > +} > + > +#if __cpp_range_based_for > +void f8 (std::vector a, std::vector b, int n) > +{ > + int i = 0; > +#pragma GCC novector > + for (int x : b) > + { > + a[i] += x; > + i++; > + } > +} > +#endif > + > +/* { 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 >