From patchwork Fri Jun 14 17:08:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 251474 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 9B54A2C0095 for ; Sat, 15 Jun 2013 03:09:13 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=nrPIY3ZbuE55imZj5MFJJVjwWYh5l SSdZjYHhhDNOki/hCXEDsZGDRD0ua9Jf2eWxycmJu4CgUX4S04HTF8VL7e6y9ic+ e163pYv/C1oxGSQHEXGpax++MPTCJNjPopj60v1Vv7jaLFbufGz6o50s8mV7piBG TesS3yXI6c7Urw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=jjb1wuKo1q2qwHT/RKlVSGFlqJw=; b=ab1 6a9FPRqKNUfO849EHuB8/ZcggbKHJ7Ygf7tF6Z/9bs+U/HN79lKqnghb0FAMH+kQ PJQXVpZ0P4t+alKBHNH0RmqG+LWFT0p22UCOBMdwKgu0S5SsIDqz81FzmVutj5s3 kmsq6hWUOVp99xi85f1i6hXWo3U7YPbpzW7Js8lA= Received: (qmail 5453 invoked by alias); 14 Jun 2013 17:09:05 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 5405 invoked by uid 89); 14 Jun 2013 17:08:58 -0000 X-Spam-SWARE-Status: No, score=-6.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS, TW_CP, TW_TM autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 14 Jun 2013 17:08:54 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r5EH8rqL012449 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 14 Jun 2013 13:08:53 -0400 Received: from zalov.cz (vpn-52-247.rdu2.redhat.com [10.10.52.247]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r5EH8orN024514 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 14 Jun 2013 13:08:52 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.cz (8.14.5/8.14.5) with ESMTP id r5EH8nVG004169; Fri, 14 Jun 2013 19:08:49 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r5EH8mJf004168; Fri, 14 Jun 2013 19:08:48 +0200 Date: Fri, 14 Jun 2013 19:08:47 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Cc: Richard Henderson , Aldy Hernandez Subject: [gomp4] C++ parsing of combined constructs Message-ID: <20130614170846.GN2336@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi! As OpenMP 4.0 is going to have far more combined constructs than we initially thought (beyond the OpenMP 2.5 parallel {for,sections} and OpenMP 4.0 rc2 {,parallel }for simd another 10-12, the initial approach I had in mind for for simd isn't really workable, so this patch revamps the parsing of combined constructs (so far in C++, C is only minimally tweaked so that OpenMP 3.1 tests keep working fine), there is a much larger function to do clause splitting, and gimplifier has been tweaked to handle those. What is left to do is handle the gimple_omp_for_combined_p constructs in omp-low.c during ompexp. The way I want it to work say for for simd is that say expand_omp_for_generic will in the usual: more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0); if (more) goto L0; else goto L3; L0: V = istart0; iend = iend0; L1: BODY; V += STEP; if (V cond iend) goto L1; else goto L2; L2: if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3; L3: sequence for collapse(1) leave the V += STEP; if (V cond iend) goto L1; else goto L2; stmts out and tweak the SIMD loop that it will start with V and end with iend. For collapsed loops we need to pass down to the expand_omp_for_simd not just start and end, but also count{2,...N}. And for distribute parallel for{, simd} we'll need a way to pass down the istart/iend and count{2,...N} for collapse>1 through parallel, thus most likely we'll want to create the decls already during gimplification and stick them somewhere, plus add them as firstprivate clauses on the parallel. Anyway, the patch grew already quite big, and this passes gomp.exp and libgomp testing and is able to compile say: int a[1024], b, c, d; void foo () { int i; #pragma omp for simd schedule(dynamic, 32) for (i = 0; i < 1024; i++) a[i] += 2; } without crashing (though, it will actually iterate 1024*1024 times right now). Thus committed to gomp-4_0-branch what I have and will continue next week. 2013-06-14 Jakub Jelinek * gimple-pretty-print.c (dump_gimple_omp_for): Don't handle GF_OMP_FOR_KIND_FOR_SIMD. * gimple.h (GF_OMP_FOR_KIND_FOR_SIMD): Remove. (GF_OMP_FOR_COMBINED): New. (gimple_omp_for_combined_p, gimple_omp_for_set_combined_p): New inline functions. * gimplify.c (is_gimple_stmt): Don't handle OMP_FOR_SIMD. (find_combined_omp_for): New function. (gimplify_omp_for): Handle combined OMP_DISTRIBUTE and OMP_FOR loops. * Makefile.in (c-family/c-omp.o): Depend on $(C_PRAGMA_H). * omp-low.c (build_outer_var_ref): Fix up simd handling. (check_omp_nesting_restrictions): Don't handle GF_OMP_FOR_KIND_FOR_SIMD. * tree.def (OMP_FOR_SIMD): Remove. * tree-pretty-print.c (dump_generic_node): Don't handle OMP_FOR_SIMD. Handle NULL OMP_FOR_INIT. c/ * c-parser.c (c_parser_omp_for): Comment out OMP_FOR_SIMD uses. (c_parser_omp_parallel): Call c_omp_split_clauses instead of c_split_parallel_clauses, adjust the code for different API of the new function. cp/ * parser.c (cp_parser_omp_all_clauses): Add defaulted finish_p argument. Don't call finish_omp_clauses if it is false. (cp_parser_omp_for_loop): Change last argument to cclauses, and adjust uses to grab parallel clauses from the array of all the split clauses. (cp_omp_split_clauses): New function. (cp_parser_omp_simd): Add p_name, mask and cclauses arguments. Allow the function to be called also when parsing combined constructs. (cp_parser_omp_sections): Likewise. (cp_parser_omp_for): Add p_name, mask and cclauses arguments. Allow the function to be called also when parsing combined constructs, and call cp_parser_omp_simd when parsing for simd. (cp_parser_omp_parallel): Likewise. (cp_parser_omp_distribute): Likewise. (cp_parser_omp_teams): Likewise. (cp_parser_omp_target): If next token is teams, call cp_parser_omp_teams and parse it as combined construct. (cp_parser_omp_declare_simd): Pass false as last argument to cp_parser_omp_all_clauses. (cp_parser_omp_construct): Adjust callers of cp_parser_omp_simd, cp_parser_omp_sections, cp_parser_omp_for, cp_parser_omp_parallel, cp_parser_omp_distribute and cp_parser_omp_teams. * pt.c (tsubst_expr): Don't handle OMP_FOR_SIMD. Handle NULL OMP_FOR_INIT. * semantics.c (finish_omp_for): Don't handle OMP_FOR_SIMD. * cp-tree.h (OMP_FOR_GIMPLIFYING_P): Adjust comment. * cp-gimplify.c (cp_gimplify_expr, cp_genericize_r): Don't handle OMP_FOR_SIMD. c-family/ * c-common.h: Move omp_clause_mask code earlier in the file. (c_omp_split_clauses): New prototype. (c_split_parallel_clauses): Removed. * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR, PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD, PRAGMA_OMP_DISTRIBUTE_SIMD, PRAGMA_OMP_TARGET_TEAMS, PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE, PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR, PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD, PRAGMA_OMP_TEAMS_DISTRIBUTE, PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR, and PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD. * c-omp.c: Include c-pragma.h. (c_omp_split_clauses): New function. (c_split_parallel_clauses): Remove. Jakub --- gcc/gimple-pretty-print.c.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/gimple-pretty-print.c 2013-06-14 12:09:18.273391612 +0200 @@ -1110,9 +1110,6 @@ dump_gimple_omp_for (pretty_printer *buf case GF_OMP_FOR_KIND_SIMD: kind = " simd"; break; - case GF_OMP_FOR_KIND_FOR_SIMD: - kind = " for simd"; - break; case GF_OMP_FOR_KIND_DISTRIBUTE: kind = " distribute"; break; @@ -1144,9 +1141,6 @@ dump_gimple_omp_for (pretty_printer *buf case GF_OMP_FOR_KIND_SIMD: pp_string (buffer, "#pragma omp simd"); break; - case GF_OMP_FOR_KIND_FOR_SIMD: - pp_string (buffer, "#pragma omp for simd"); - break; case GF_OMP_FOR_KIND_DISTRIBUTE: pp_string (buffer, "#pragma omp distribute"); break; --- gcc/c/c-parser.c.jj 2013-05-13 16:36:52.000000000 +0200 +++ gcc/c/c-parser.c 2013-06-14 12:09:18.276392262 +0200 @@ -11044,7 +11044,7 @@ c_parser_omp_for (location_t loc, c_pars if (strcmp (p, "simd") == 0) { c_parser_consume_token (parser); - code = OMP_FOR_SIMD; + /* code = OMP_FOR_SIMD; */ mask |= OMP_SIMD_CLAUSE_MASK; p_name = "#pragma omp for simd"; } @@ -11234,6 +11234,7 @@ c_parser_omp_parallel (location_t loc, c const char *p_name = "#pragma omp parallel"; tree stmt, clauses, par_clause, ws_clause, block; omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK; + tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT]; if (c_parser_next_token_is_keyword (parser, RID_FOR)) { @@ -11280,7 +11281,9 @@ c_parser_omp_parallel (location_t loc, c case PRAGMA_OMP_PARALLEL_FOR: block = c_begin_omp_parallel (); - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); + c_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses); + par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; c_parser_omp_for_loop (loc, parser, OMP_FOR, ws_clause, &par_clause); stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; @@ -11288,8 +11291,10 @@ c_parser_omp_parallel (location_t loc, c case PRAGMA_OMP_PARALLEL_FOR_SIMD: block = c_begin_omp_parallel (); - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); - c_parser_omp_for_loop (loc, parser, OMP_FOR_SIMD, ws_clause, + c_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses); + par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; + c_parser_omp_for_loop (loc, parser, OMP_FOR /*_SIMD*/, ws_clause, &par_clause); stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; @@ -11297,7 +11302,9 @@ c_parser_omp_parallel (location_t loc, c case PRAGMA_OMP_PARALLEL_SECTIONS: block = c_begin_omp_parallel (); - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); + c_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses); + par_clause = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + ws_clause = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]; stmt = c_parser_omp_sections_scope (loc, parser); if (stmt) OMP_SECTIONS_CLAUSES (stmt) = ws_clause; --- gcc/cp/parser.c.jj 2013-06-12 15:00:11.000000000 +0200 +++ gcc/cp/parser.c 2013-06-14 13:22:11.291742674 +0200 @@ -27299,7 +27299,8 @@ cp_parser_omp_clause_proc_bind (cp_parse static tree cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, - const char *where, cp_token *pragma_tok) + const char *where, cp_token *pragma_tok, + bool finish_p = true) { tree clauses = NULL; bool first = true; @@ -27526,9 +27527,9 @@ cp_parser_omp_all_clauses (cp_parser *pa } saw_error: cp_parser_skip_to_pragma_eol (parser, pragma_tok); - if (parser->omp_declare_simd_clauses) - return clauses; - return finish_omp_clauses (clauses); + if (finish_p) + return finish_omp_clauses (clauses); + return clauses; } /* OpenMP 2.5: @@ -28202,7 +28203,7 @@ cp_parser_omp_for_incr (cp_parser *parse static tree cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, - tree *par_clauses) + tree *cclauses) { tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret; tree real_decl, initv, condv, incrv, declv; @@ -28412,10 +28413,12 @@ cp_parser_omp_for_loop (cp_parser *parse if (decl) real_decl = decl; - if (par_clauses != NULL && real_decl != NULL_TREE) + if (cclauses != NULL + && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL + && real_decl != NULL_TREE) { tree *c; - for (c = par_clauses; *c ; ) + for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; ) if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE && OMP_CLAUSE_DECL (*c) == real_decl) { @@ -28594,6 +28597,20 @@ cp_parser_omp_for_loop (cp_parser *parse return ret; } +/* Helper function for OpenMP parsing, split clauses and call + finish_omp_clauses on each of the set of clauses afterwards. */ + +static void +cp_omp_split_clauses (location_t loc, enum tree_code code, + omp_clause_mask mask, tree clauses, tree *cclauses) +{ + int i; + c_omp_split_clauses (loc, code, mask, clauses, cclauses); + for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) + if (cclauses[i]) + cclauses[i] = finish_omp_clauses (cclauses[i]); +} + /* OpenMP 4.0: #pragma omp simd simd-clause[optseq] new-line for-loop */ @@ -28608,18 +28625,29 @@ cp_parser_omp_for_loop (cp_parser *parse | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) static tree -cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) { tree clauses, sb, ret; unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; - clauses = cp_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK, - "#pragma omp simd", pragma_tok); + strcat (p_name, " simd"); + mask |= OMP_SIMD_CLAUSE_MASK; + mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED); + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; + } sb = begin_omp_structured_block (); save = cp_parser_begin_omp_structured_block (parser); - ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, NULL); + ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses); cp_parser_end_omp_structured_block (parser, save); add_stmt (finish_omp_structured_block (sb)); @@ -28646,13 +28674,17 @@ cp_parser_omp_simd (cp_parser *parser, c | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) static tree -cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) { tree clauses, sb, ret; unsigned int save; - enum tree_code code = OMP_FOR; - omp_clause_mask mask = OMP_FOR_CLAUSE_MASK; - const char *p_name = "#pragma omp for"; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " for"); + mask |= OMP_FOR_CLAUSE_MASK; + if (cclauses) + mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -28661,19 +28693,41 @@ cp_parser_omp_for (cp_parser *parser, cp if (strcmp (p, "simd") == 0) { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + cp_lexer_consume_token (parser->lexer); - code = OMP_FOR_SIMD; - mask |= OMP_SIMD_CLAUSE_MASK; - p_name = "#pragma omp for simd"; + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, + cclauses); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + ret = make_node (OMP_FOR); + TREE_TYPE (ret) = void_type_node; + OMP_FOR_BODY (ret) = body; + OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; + SET_EXPR_LOCATION (ret, loc); + add_stmt (ret); + return ret; } } - clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok); + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; + } sb = begin_omp_structured_block (); save = cp_parser_begin_omp_structured_block (parser); - ret = cp_parser_omp_for_loop (parser, code, clauses, NULL); + ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses); cp_parser_end_omp_structured_block (parser, save); add_stmt (finish_omp_structured_block (sb)); @@ -28800,12 +28854,24 @@ cp_parser_omp_sections_scope (cp_parser | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree -cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) { tree clauses, ret; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; - clauses = cp_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK, - "#pragma omp sections", pragma_tok); + strcat (p_name, " sections"); + mask |= OMP_SECTIONS_CLAUSE_MASK; + if (cclauses) + mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]; + } ret = cp_parser_omp_sections_scope (parser); if (ret) @@ -28834,35 +28900,37 @@ cp_parser_omp_sections (cp_parser *parse | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND)) static tree -cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) { - enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL; - const char *p_name = "#pragma omp parallel"; - tree stmt, clauses, par_clause, ws_clause, block; - omp_clause_mask mask = OMP_PARALLEL_CLAUSE_MASK; + tree stmt, clauses, block; unsigned int save; location_t loc = cp_lexer_peek_token (parser->lexer)->location; + strcat (p_name, " parallel"); + mask |= OMP_PARALLEL_CLAUSE_MASK; + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) { - cp_lexer_consume_token (parser->lexer); - p_kind = PRAGMA_OMP_PARALLEL_FOR; - p_name = "#pragma omp parallel for"; - mask |= OMP_FOR_CLAUSE_MASK; - mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); - if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) - { - tree id = cp_lexer_peek_token (parser->lexer)->u.value; - const char *p = IDENTIFIER_POINTER (id); + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; - if (strcmp (p, "simd") == 0) - { - cp_lexer_consume_token (parser->lexer); - p_kind = PRAGMA_OMP_PARALLEL_FOR_SIMD; - p_name = "#pragma omp parallel for simd"; - mask |= OMP_SIMD_CLAUSE_MASK; - } - } + cp_lexer_consume_token (parser->lexer); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses); + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; + } + else if (cclauses) + { + error_at (loc, "expected % after %qs", p_name); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; } else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -28870,50 +28938,28 @@ cp_parser_omp_parallel (cp_parser *parse const char *p = IDENTIFIER_POINTER (id); if (strcmp (p, "sections") == 0) { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + cclauses = cclauses_buf; + cp_lexer_consume_token (parser->lexer); - p_kind = PRAGMA_OMP_PARALLEL_SECTIONS; - p_name = "#pragma omp parallel sections"; - mask |= OMP_SECTIONS_CLAUSE_MASK; - mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + cp_parser_omp_sections (parser, pragma_tok, p_name, mask, cclauses); + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; } } clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok); + block = begin_omp_parallel (); save = cp_parser_begin_omp_structured_block (parser); - - switch (p_kind) - { - case PRAGMA_OMP_PARALLEL: - cp_parser_statement (parser, NULL_TREE, false, NULL); - par_clause = clauses; - break; - - case PRAGMA_OMP_PARALLEL_FOR: - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); - cp_parser_omp_for_loop (parser, OMP_FOR, ws_clause, &par_clause); - break; - - case PRAGMA_OMP_PARALLEL_FOR_SIMD: - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); - cp_parser_omp_for_loop (parser, OMP_FOR_SIMD, ws_clause, &par_clause); - break; - - case PRAGMA_OMP_PARALLEL_SECTIONS: - c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); - stmt = cp_parser_omp_sections_scope (parser); - if (stmt) - OMP_SECTIONS_CLAUSES (stmt) = ws_clause; - break; - - default: - gcc_unreachable (); - } - + cp_parser_statement (parser, NULL_TREE, false, NULL); cp_parser_end_omp_structured_block (parser, save); - stmt = finish_omp_parallel (par_clause, block); - if (p_kind != PRAGMA_OMP_PARALLEL) - OMP_PARALLEL_COMBINED (stmt) = 1; + stmt = finish_omp_parallel (clauses, block); return stmt; } @@ -29088,6 +29134,92 @@ cp_parser_omp_cancellation_point (cp_par } /* OpenMP 4.0: + #pragma omp distribute distribute-clause[optseq] new-line + for-loop */ + +#define OMP_DISTRIBUTE_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) + +static tree +cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) +{ + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " distribute"); + mask |= OMP_DISTRIBUTE_CLAUSE_MASK; + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + bool simd = false; + bool parallel = false; + + if (strcmp (p, "simd") == 0) + { + simd = true; + if (cclauses) + { + error_at (loc, "% not expected after %qs", p_name); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + } + else + parallel = strcmp (p, "parallel") == 0; + if (parallel || simd) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + if (simd) + ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, + cclauses); + else + ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, + cclauses); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + ret = make_node (OMP_DISTRIBUTE); + TREE_TYPE (ret) = void_type_node; + OMP_FOR_BODY (ret) = body; + OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; + SET_EXPR_LOCATION (ret, loc); + add_stmt (ret); + return ret; + } + } + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE]; + } + + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + + ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL); + + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + + return ret; +} + +/* OpenMP 4.0: # pragma omp teams teams-clause[optseq] new-line structured-block */ @@ -29101,14 +29233,55 @@ cp_parser_omp_cancellation_point (cp_par | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT)) static tree -cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok) +cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses) { + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " teams"); + mask |= OMP_TEAMS_CLAUSE_MASK; + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + if (strcmp (p, "distribute") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, + cclauses); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + ret = make_node (OMP_TEAMS); + TREE_TYPE (ret) = void_type_node; + OMP_TEAMS_CLAUSES (ret) = clauses; + OMP_TEAMS_BODY (ret) = body; + return add_stmt (ret); + } + } + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + cclauses == NULL); + if (cclauses) + { + cp_omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses); + clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + } + tree stmt = make_node (OMP_TEAMS); TREE_TYPE (stmt) = void_type_node; - - OMP_TEAMS_CLAUSES (stmt) - = cp_parser_omp_all_clauses (parser, OMP_TEAMS_CLAUSE_MASK, - "#pragma omp teams", pragma_tok); + OMP_TEAMS_CLAUSES (stmt) = clauses; OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser); return add_stmt (stmt); @@ -29216,6 +29389,29 @@ cp_parser_omp_target (cp_parser *parser, cp_lexer_consume_token (parser->lexer); return cp_parser_omp_target_update (parser, pragma_tok, context); } + else if (strcmp (p, "teams") == 0) + { + tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT]; + char p_name[sizeof ("#pragma omp target teams distribute " + "parallel for simd")]; + + cp_lexer_consume_token (parser->lexer); + strcpy (p_name, "#pragma omp target"); + tree sb = begin_omp_structured_block (); + unsigned save = cp_parser_begin_omp_structured_block (parser); + tree ret = cp_parser_omp_teams (parser, pragma_tok, p_name, + OMP_TARGET_CLAUSE_MASK, cclauses); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + tree stmt = make_node (OMP_TARGET); + TREE_TYPE (stmt) = void_type_node; + OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + OMP_TARGET_BODY (stmt) = body; + add_stmt (stmt); + return true; + } } tree stmt = make_node (OMP_TARGET); @@ -29232,36 +29428,6 @@ cp_parser_omp_target (cp_parser *parser, } /* OpenMP 4.0: - #pragma omp distribute distribute-clause[optseq] new-line - for-loop */ - -#define OMP_DISTRIBUTE_CLAUSE_MASK \ - ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\ - | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE)) - -static tree -cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok) -{ - tree clauses, sb, ret; - unsigned int save; - - clauses = cp_parser_omp_all_clauses (parser, OMP_DISTRIBUTE_CLAUSE_MASK, - "#pragma omp distribute", pragma_tok); - - sb = begin_omp_structured_block (); - save = cp_parser_begin_omp_structured_block (parser); - - ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL); - - cp_parser_end_omp_structured_block (parser, save); - add_stmt (finish_omp_structured_block (sb)); - - return ret; -} - -/* OpenMP 4.0: # pragma omp declare simd declare-simd-clauses[optseq] new-line */ #define OMP_DECLARE_SIMD_CLAUSE_MASK \ @@ -29281,7 +29447,8 @@ cp_parser_omp_declare_simd (cp_parser *p vec_safe_push (parser->omp_declare_simd_clauses, NULL_TREE); tree clauses = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, - "#pragma omp declare simd", pragma_tok); + "#pragma omp declare simd", pragma_tok, + false); parser->omp_declare_simd_clauses->last () = clauses; if (first_p) { @@ -29382,6 +29549,8 @@ static void cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok) { tree stmt; + char p_name[sizeof "#pragma omp teams distribute parallel for simd"]; + omp_clause_mask mask (0); switch (pragma_tok->pragma_kind) { @@ -29392,10 +29561,12 @@ cp_parser_omp_construct (cp_parser *pars stmt = cp_parser_omp_critical (parser, pragma_tok); break; case PRAGMA_OMP_DISTRIBUTE: - stmt = cp_parser_omp_distribute (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL); break; case PRAGMA_OMP_FOR: - stmt = cp_parser_omp_for (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL); break; case PRAGMA_OMP_MASTER: stmt = cp_parser_omp_master (parser, pragma_tok); @@ -29404,13 +29575,16 @@ cp_parser_omp_construct (cp_parser *pars stmt = cp_parser_omp_ordered (parser, pragma_tok); break; case PRAGMA_OMP_PARALLEL: - stmt = cp_parser_omp_parallel (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL); break; case PRAGMA_OMP_SECTIONS: - stmt = cp_parser_omp_sections (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_sections (parser, pragma_tok, p_name, mask, NULL); break; case PRAGMA_OMP_SIMD: - stmt = cp_parser_omp_simd (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL); break; case PRAGMA_OMP_SINGLE: stmt = cp_parser_omp_single (parser, pragma_tok); @@ -29422,7 +29596,8 @@ cp_parser_omp_construct (cp_parser *pars cp_parser_omp_taskgroup (parser, pragma_tok); return; case PRAGMA_OMP_TEAMS: - stmt = cp_parser_omp_teams (parser, pragma_tok); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL); break; default: gcc_unreachable (); --- gcc/cp/pt.c.jj 2013-06-12 14:59:07.000000000 +0200 +++ gcc/cp/pt.c 2013-06-14 17:45:22.066675980 +0200 @@ -13293,19 +13293,22 @@ tsubst_expr (tree t, tree args, tsubst_f case OMP_FOR: case OMP_SIMD: - case OMP_FOR_SIMD: case OMP_DISTRIBUTE: { tree clauses, body, pre_body; - tree declv, initv, condv, incrv; + tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE; + tree incrv = NULL_TREE; int i; clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false, args, complain, in_decl); - declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); - initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); - condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); - incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + if (OMP_FOR_INIT (t) != NULL_TREE) + { + declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + } stmt = begin_omp_structured_block (); @@ -13313,17 +13316,29 @@ tsubst_expr (tree t, tree args, tsubst_f RECUR (OMP_FOR_PRE_BODY (t)); pre_body = pop_stmt_list (pre_body); - for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) - tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv, - &clauses, args, complain, in_decl, - integral_constant_expression_p); + if (OMP_FOR_INIT (t) != NULL_TREE) + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) + tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv, + &clauses, args, complain, in_decl, + integral_constant_expression_p); body = push_stmt_list (); RECUR (OMP_FOR_BODY (t)); body = pop_stmt_list (body); - t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv, - condv, incrv, body, pre_body, clauses); + if (OMP_FOR_INIT (t) != NULL_TREE) + t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv, + condv, incrv, body, pre_body, clauses); + else + { + t = make_node (TREE_CODE (t)); + TREE_TYPE (t) = void_type_node; + OMP_FOR_BODY (t) = body; + OMP_FOR_PRE_BODY (t) = pre_body; + OMP_FOR_CLAUSES (t) = clauses; + SET_EXPR_LOCATION (t, EXPR_LOCATION (t)); + add_stmt (t); + } add_stmt (finish_omp_structured_block (stmt)); } --- gcc/cp/semantics.c.jj 2013-06-12 15:00:11.000000000 +0200 +++ gcc/cp/semantics.c 2013-06-14 12:09:18.287394537 +0200 @@ -5760,11 +5782,10 @@ finish_omp_for (location_t locus, enum t if (CLASS_TYPE_P (TREE_TYPE (decl))) { - if (code == OMP_SIMD || code == OMP_FOR_SIMD) + if (code == OMP_SIMD) { - error_at (elocus, "%<#pragma omp%s simd%> used with class " - "iteration variable %qE", - code == OMP_FOR_SIMD ? " for" : "", decl); + error_at (elocus, "%<#pragma omp simd%> used with class " + "iteration variable %qE", decl); return NULL; } if (handle_omp_for_class_iterator (i, locus, declv, initv, condv, --- gcc/cp/cp-tree.h.jj 2013-05-29 10:05:42.000000000 +0200 +++ gcc/cp/cp-tree.h 2013-06-13 12:26:37.480571572 +0200 @@ -60,8 +60,7 @@ c-common.h, not after. STMT_EXPR_NO_SCOPE (in STMT_EXPR) BIND_EXPR_TRY_BLOCK (in BIND_EXPR) TYPENAME_IS_ENUM_P (in TYPENAME_TYPE) - OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD, OMP_FOR_SIMD - and OMP_DISTRIBUTE) + OMP_FOR_GIMPLIFYING_P (in OMP_FOR, OMP_SIMD and OMP_DISTRIBUTE) BASELINK_QUALIFIED_P (in BASELINK) TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) --- gcc/cp/cp-gimplify.c.jj 2013-05-13 16:38:25.000000000 +0200 +++ gcc/cp/cp-gimplify.c 2013-06-14 12:09:18.290395129 +0200 @@ -670,7 +670,6 @@ cp_gimplify_expr (tree *expr_p, gimple_s case OMP_FOR: case OMP_SIMD: - case OMP_FOR_SIMD: case OMP_DISTRIBUTE: ret = cp_gimplify_omp_for (expr_p, pre_p); break; @@ -1121,7 +1120,6 @@ cp_genericize_r (tree *stmt_p, int *walk genericize_break_stmt (stmt_p); else if (TREE_CODE (stmt) == OMP_FOR || TREE_CODE (stmt) == OMP_SIMD - || TREE_CODE (stmt) == OMP_FOR_SIMD || TREE_CODE (stmt) == OMP_DISTRIBUTE) genericize_omp_for_stmt (stmt_p, walk_subtrees, data); else if (TREE_CODE (stmt) == SIZEOF_EXPR) --- gcc/gimple.h.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/gimple.h 2013-06-14 16:27:40.920798468 +0200 @@ -113,8 +113,8 @@ enum gf_mask { GF_OMP_FOR_KIND_MASK = 3 << 0, GF_OMP_FOR_KIND_FOR = 0 << 0, GF_OMP_FOR_KIND_SIMD = 1 << 0, - GF_OMP_FOR_KIND_FOR_SIMD = 2 << 0, - GF_OMP_FOR_KIND_DISTRIBUTE = 3 << 0, + GF_OMP_FOR_KIND_DISTRIBUTE = 2 << 0, + GF_OMP_FOR_COMBINED = 4 << 0, GF_OMP_TARGET_KIND_MASK = 3 << 0, GF_OMP_TARGET_KIND_REGION = 0 << 0, GF_OMP_TARGET_KIND_DATA = 1 << 0, @@ -4003,6 +4003,31 @@ gimple_omp_for_set_kind (gimple g, int k } +/* Return true if OMP for statement G has the + GF_OMP_FOR_COMBINED flag set. */ + +static inline bool +gimple_omp_for_combined_p (const_gimple g) +{ + GIMPLE_CHECK (g, GIMPLE_OMP_FOR); + return (gimple_omp_subcode (g) & GF_OMP_FOR_COMBINED) != 0; +} + + +/* Set the GF_OMP_FOR_COMBINED field in G depending on the boolean + value of COMBINED_P. */ + +static inline void +gimple_omp_for_set_combined_p (gimple g, bool combined_p) +{ + GIMPLE_CHECK (g, GIMPLE_OMP_FOR); + if (combined_p) + g->gsbase.subcode |= GF_OMP_FOR_COMBINED; + else + g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED; +} + + /* Return the clauses associated with OMP_FOR GS. */ static inline tree --- gcc/gimplify.c.jj 2013-06-12 14:59:07.000000000 +0200 +++ gcc/gimplify.c 2013-06-14 16:33:31.877024772 +0200 @@ -4716,7 +4716,6 @@ is_gimple_stmt (tree t) case OMP_PARALLEL: case OMP_FOR: case OMP_SIMD: - case OMP_FOR_SIMD: case OMP_DISTRIBUTE: case OMP_SECTIONS: case OMP_SECTION: @@ -6826,12 +6825,39 @@ gimplify_omp_task (tree *expr_p, gimple_ *expr_p = NULL_TREE; } +/* Helper function of gimplify_omp_for, find OMP_FOR resp. OMP_SIMD + with non-NULL OMP_FOR_INIT. */ + +static tree +find_combined_omp_for (tree *tp, int *walk_subtrees, void *) +{ + *walk_subtrees = 0; + switch (TREE_CODE (*tp)) + { + case OMP_FOR: + *walk_subtrees = 1; + /* FALLTHRU */ + case OMP_SIMD: + if (OMP_FOR_INIT (*tp) != NULL_TREE) + return *tp; + break; + case BIND_EXPR: + case STATEMENT_LIST: + case OMP_PARALLEL: + *walk_subtrees = 1; + break; + default: + break; + } + return NULL_TREE; +} + /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) { - tree for_stmt, decl, var, t; + tree for_stmt, orig_for_stmt, decl, var, t; enum gimplify_status ret = GS_ALL_DONE; enum gimplify_status tret; gimple gfor; @@ -6840,10 +6866,9 @@ gimplify_omp_for (tree *expr_p, gimple_s bool simd; bitmap has_decl_expr = NULL; - for_stmt = *expr_p; + orig_for_stmt = for_stmt = *expr_p; - simd = TREE_CODE (for_stmt) == OMP_SIMD - || TREE_CODE (for_stmt) == OMP_FOR_SIMD; + simd = TREE_CODE (for_stmt) == OMP_SIMD; gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, TREE_CODE (for_stmt) == OMP_SIMD ? ORT_SIMD : ORT_WORKSHARE); @@ -6876,6 +6901,13 @@ gimplify_omp_for (tree *expr_p, gimple_s gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body); OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE; + if (OMP_FOR_INIT (for_stmt) == NULL_TREE) + { + for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt), find_combined_omp_for, + NULL, NULL); + gcc_assert (for_stmt != NULL_TREE); + } + for_body = NULL; gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt))); @@ -6891,12 +6923,14 @@ gimplify_omp_for (tree *expr_p, gimple_s || POINTER_TYPE_P (TREE_TYPE (decl))); /* Make sure the iteration variable is private. */ - bool is_private = omp_is_private (gimplify_omp_ctxp, decl, simd); tree c = NULL_TREE; - if (simd) + if (orig_for_stmt != for_stmt) + /* Do this only on innermost construct for combined ones. */; + else if (simd) { splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables, (splay_tree_key)decl); + omp_is_private (gimplify_omp_ctxp, decl, simd); if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0) omp_notice_variable (gimplify_omp_ctxp, decl, true); else @@ -6913,7 +6947,7 @@ gimplify_omp_for (tree *expr_p, gimple_s GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN); } } - else if (is_private) + else if (omp_is_private (gimplify_omp_ctxp, decl, simd)) omp_notice_variable (gimplify_omp_ctxp, decl, true); else omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN); @@ -6921,7 +6955,9 @@ gimplify_omp_for (tree *expr_p, gimple_s /* If DECL is not a gimple register, create a temporary variable to act as an iteration counter. This is valid, since DECL cannot be modified in the body of the loop. */ - if (!is_gimple_reg (decl)) + if (orig_for_stmt != for_stmt) + var = decl; + else if (!is_gimple_reg (decl)) { var = create_tmp_var (TREE_TYPE (decl), get_name (decl)); TREE_OPERAND (t, 0) = var; @@ -6954,6 +6990,8 @@ gimplify_omp_for (tree *expr_p, gimple_s { case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: + if (orig_for_stmt != for_stmt) + break; t = build_int_cst (TREE_TYPE (decl), 1); if (c) OMP_CLAUSE_LINEAR_STEP (c) = t; @@ -6964,6 +7002,8 @@ gimplify_omp_for (tree *expr_p, gimple_s case PREDECREMENT_EXPR: case POSTDECREMENT_EXPR: + if (orig_for_stmt != for_stmt) + break; t = build_int_cst (TREE_TYPE (decl), -1); if (c) OMP_CLAUSE_LINEAR_STEP (c) = t; @@ -7020,7 +7060,8 @@ gimplify_omp_for (tree *expr_p, gimple_s gcc_unreachable (); } - if (var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1) + if ((var != decl || TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1) + && orig_for_stmt == for_stmt) { for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE @@ -7045,23 +7086,37 @@ gimplify_omp_for (tree *expr_p, gimple_s BITMAP_FREE (has_decl_expr); - gimplify_and_add (OMP_FOR_BODY (for_stmt), &for_body); + gimplify_and_add (OMP_FOR_BODY (orig_for_stmt), &for_body); + + if (orig_for_stmt != for_stmt) + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) + { + t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); + decl = TREE_OPERAND (t, 0); + var = create_tmp_var (TREE_TYPE (decl), get_name (decl)); + omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN); + TREE_OPERAND (t, 0) = var; + t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); + TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1)); + TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var; + } - gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt)); + gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt)); int kind; - switch (TREE_CODE (for_stmt)) + switch (TREE_CODE (orig_for_stmt)) { case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break; case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break; - case OMP_FOR_SIMD: kind = GF_OMP_FOR_KIND_FOR_SIMD; break; case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break; default: gcc_unreachable (); } - gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (for_stmt), + gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt), TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)), for_pre_body); + if (orig_for_stmt != for_stmt) + gimple_omp_for_set_combined_p (gfor, true); for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) { @@ -8057,7 +8112,6 @@ gimplify_expr (tree *expr_p, gimple_seq case OMP_FOR: case OMP_SIMD: - case OMP_FOR_SIMD: case OMP_DISTRIBUTE: ret = gimplify_omp_for (expr_p, pre_p); break; --- gcc/Makefile.in.jj 2013-06-12 11:53:15.000000000 +0200 +++ gcc/Makefile.in 2013-06-12 11:53:15.000000000 +0200 @@ -1976,7 +1976,7 @@ c-family/c-lex.o : c-family/c-lex.c $(CO $(CPPLIB_H) $(TARGET_H) $(TIMEVAR_H) c-family/c-omp.o : c-family/c-omp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TREE_H) $(C_COMMON_H) $(GIMPLE_H) langhooks.h + $(TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(GIMPLE_H) langhooks.h CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@ c-family/c-opts.o : c-family/c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ --- gcc/omp-low.c.jj 2013-06-12 11:53:14.000000000 +0200 +++ gcc/omp-low.c 2013-06-14 16:19:10.595129024 +0200 @@ -938,17 +938,25 @@ build_outer_var_ref (tree var, omp_conte bool by_ref = use_pointer_for_field (var, NULL); x = build_receiver_ref (var, by_ref, ctx); } + else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) + { + /* #pragma omp simd isn't a worksharing construct, and can reference even + private vars in its linear etc. clauses. */ + x = NULL_TREE; + if (ctx->outer && is_taskreg_ctx (ctx)) + x = lookup_decl (var, ctx->outer); + else if (ctx->outer) + x = maybe_lookup_decl (var, ctx->outer); + if (x == NULL_TREE) + x = var; + } else if (ctx->outer) x = lookup_decl (var, ctx->outer); else if (is_reference (var)) /* This can happen with orphaned constructs. If var is reference, it is possible it is shared and as such valid. */ x = var; - else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) - /* #pragma omp simd isn't a worksharing construct, and can reference even - private vars in its linear etc. clauses. */ - x = var; else gcc_unreachable (); @@ -1877,8 +1885,7 @@ check_omp_nesting_restrictions (gimple s if (ctx != NULL) { if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD - || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR_SIMD)) + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD) { error_at (gimple_location (stmt), "OpenMP constructs may not be nested inside simd region"); --- gcc/tree.def.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/tree.def 2013-06-13 11:55:43.242627832 +0200 @@ -1034,10 +1034,6 @@ DEFTREECODE (OMP_FOR, "omp_for", tcc_sta Operands like for OMP_FOR. */ DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6) -/* OpenMP - #pragma omp for simd [clause1 ... clauseN] - Operands like for OMP_FOR. */ -DEFTREECODE (OMP_FOR_SIMD, "omp_for_simd", tcc_statement, 6) - /* OpenMP - #pragma omp distribute [clause1 ... clauseN] Operands like for OMP_FOR. */ DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6) --- gcc/tree-pretty-print.c.jj 2013-06-12 14:59:07.000000000 +0200 +++ gcc/tree-pretty-print.c 2013-06-14 13:31:19.236871998 +0200 @@ -2364,10 +2364,6 @@ dump_generic_node (pretty_printer *buffe pp_string (buffer, "#pragma omp simd"); goto dump_omp_loop; - case OMP_FOR_SIMD: - pp_string (buffer, "#pragma omp for simd"); - goto dump_omp_loop; - case OMP_DISTRIBUTE: pp_string (buffer, "#pragma omp distribute"); goto dump_omp_loop; @@ -2409,21 +2405,27 @@ dump_generic_node (pretty_printer *buffe dump_generic_node (buffer, OMP_FOR_PRE_BODY (node), spc, flags, false); } - spc -= 2; - for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++) + if (OMP_FOR_INIT (node)) { - spc += 2; - newline_and_indent (buffer, spc); - pp_string (buffer, "for ("); - dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INIT (node), i), - spc, flags, false); - pp_string (buffer, "; "); - dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_COND (node), i), - spc, flags, false); - pp_string (buffer, "; "); - dump_generic_node (buffer, TREE_VEC_ELT (OMP_FOR_INCR (node), i), - spc, flags, false); - pp_string (buffer, ")"); + spc -= 2; + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++) + { + spc += 2; + newline_and_indent (buffer, spc); + pp_string (buffer, "for ("); + dump_generic_node (buffer, + TREE_VEC_ELT (OMP_FOR_INIT (node), i), + spc, flags, false); + pp_string (buffer, "; "); + dump_generic_node (buffer, + TREE_VEC_ELT (OMP_FOR_COND (node), i), + spc, flags, false); + pp_string (buffer, "; "); + dump_generic_node (buffer, + TREE_VEC_ELT (OMP_FOR_INCR (node), i), + spc, flags, false); + pp_string (buffer, ")"); + } } if (OMP_FOR_BODY (node)) { @@ -2435,7 +2437,8 @@ dump_generic_node (pretty_printer *buffe newline_and_indent (buffer, spc + 2); pp_character (buffer, '}'); } - spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2; + if (OMP_FOR_INIT (node)) + spc -= 2 * TREE_VEC_LENGTH (OMP_FOR_INIT (node)) - 2; if (OMP_FOR_PRE_BODY (node)) { spc -= 4; --- gcc/c-family/c-common.h.jj 2013-05-09 17:06:21.000000000 +0200 +++ gcc/c-family/c-common.h 2013-06-13 18:07:18.388364356 +0200 @@ -1030,112 +1030,6 @@ extern void pp_dir_change (cpp_reader *, extern bool check_missing_format_attribute (tree, tree); /* In c-omp.c */ -extern tree c_finish_omp_master (location_t, tree); -extern tree c_finish_omp_critical (location_t, tree, tree); -extern tree c_finish_omp_ordered (location_t, tree); -extern void c_finish_omp_barrier (location_t); -extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, - tree, tree, tree, tree, tree, bool, bool); -extern void c_finish_omp_flush (location_t); -extern void c_finish_omp_taskwait (location_t); -extern void c_finish_omp_taskyield (location_t); -extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree, - tree, tree, tree); -extern void c_split_parallel_clauses (location_t, tree, tree *, tree *); -extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree); -extern void c_omp_declare_simd_clauses_to_decls (tree, tree); -extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); - -/* Not in c-omp.c; provided by the front end. */ -extern bool c_omp_sharing_predetermined (tree); -extern tree c_omp_remap_decl (tree, bool); -extern void record_types_used_by_current_var_decl (tree); - -/* Return next tree in the chain for chain_next walking of tree nodes. */ -static inline tree -c_tree_chain_next (tree t) -{ - /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different - kind of object, never a long chain of nodes. Prefer - TYPE_NEXT_VARIANT for types. */ - if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON)) - return TYPE_NEXT_VARIANT (t); - /* Otherwise, if there is TREE_CHAIN, return it. */ - if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON)) - return TREE_CHAIN (t); - return NULL; -} - -/* Mask used by tm_stmt_attr. */ -#define TM_STMT_ATTR_OUTER 2 -#define TM_STMT_ATTR_ATOMIC 4 -#define TM_STMT_ATTR_RELAXED 8 - -extern int parse_tm_stmt_attr (tree, int); - -/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these - are ordered specifically such that more restrictive attributes are - at lower bit positions. This fact is known by the C++ tm attribute - inheritance code such that least bit extraction (mask & -mask) results - in the most restrictive attribute. */ -#define TM_ATTR_SAFE 1 -#define TM_ATTR_CALLABLE 2 -#define TM_ATTR_PURE 4 -#define TM_ATTR_IRREVOCABLE 8 -#define TM_ATTR_MAY_CANCEL_OUTER 16 - -extern int tm_attr_to_mask (tree); -extern tree tm_mask_to_attr (int); -extern tree find_tm_attribute (tree); - -/* A suffix-identifier value doublet that represents user-defined literals - for C++-0x. */ -enum overflow_type { - OT_UNDERFLOW = -1, - OT_NONE, - OT_OVERFLOW -}; - -struct GTY(()) tree_userdef_literal { - struct tree_base base; - tree suffix_id; - tree value; - tree num_string; - enum overflow_type overflow; -}; - -#define USERDEF_LITERAL_SUFFIX_ID(NODE) \ - (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id) - -#define USERDEF_LITERAL_VALUE(NODE) \ - (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value) - -#define USERDEF_LITERAL_OVERFLOW(NODE) \ - (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow) - -#define USERDEF_LITERAL_NUM_STRING(NODE) \ - (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string) - -#define USERDEF_LITERAL_TYPE(NODE) \ - (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE))) - -extern tree build_userdef_literal (tree suffix_id, tree value, - enum overflow_type overflow, - tree num_string); - -extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree); - -/* Possibe cases of scalar_to_vector conversion. */ -enum stv_conv { - stv_error, /* Error occured. */ - stv_nothing, /* Nothing happened. */ - stv_firstarg, /* First argument must be expanded. */ - stv_secondarg /* Second argument must be expanded. */ -}; - -extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code, - tree op0, tree op1, bool); - #if HOST_BITS_PER_WIDE_INT >= 64 typedef unsigned HOST_WIDE_INT omp_clause_mask; # define OMP_CLAUSE_MASK_1 ((omp_clause_mask) 1) @@ -1261,4 +1155,123 @@ omp_clause_mask::operator == (omp_clause # define OMP_CLAUSE_MASK_1 omp_clause_mask (1) #endif +enum c_omp_clause_split +{ + C_OMP_CLAUSE_SPLIT_TARGET = 0, + C_OMP_CLAUSE_SPLIT_TEAMS, + C_OMP_CLAUSE_SPLIT_DISTRIBUTE, + C_OMP_CLAUSE_SPLIT_PARALLEL, + C_OMP_CLAUSE_SPLIT_FOR, + C_OMP_CLAUSE_SPLIT_SIMD, + C_OMP_CLAUSE_SPLIT_COUNT, + C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR +}; + +extern tree c_finish_omp_master (location_t, tree); +extern tree c_finish_omp_critical (location_t, tree, tree); +extern tree c_finish_omp_ordered (location_t, tree); +extern void c_finish_omp_barrier (location_t); +extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, + tree, tree, tree, tree, tree, bool, bool); +extern void c_finish_omp_flush (location_t); +extern void c_finish_omp_taskwait (location_t); +extern void c_finish_omp_taskyield (location_t); +extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree, + tree, tree, tree); +extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask, + tree, tree *); +extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree); +extern void c_omp_declare_simd_clauses_to_decls (tree, tree); +extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); + +/* Not in c-omp.c; provided by the front end. */ +extern bool c_omp_sharing_predetermined (tree); +extern tree c_omp_remap_decl (tree, bool); +extern void record_types_used_by_current_var_decl (tree); + +/* Return next tree in the chain for chain_next walking of tree nodes. */ +static inline tree +c_tree_chain_next (tree t) +{ + /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different + kind of object, never a long chain of nodes. Prefer + TYPE_NEXT_VARIANT for types. */ + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON)) + return TYPE_NEXT_VARIANT (t); + /* Otherwise, if there is TREE_CHAIN, return it. */ + if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON)) + return TREE_CHAIN (t); + return NULL; +} + +/* Mask used by tm_stmt_attr. */ +#define TM_STMT_ATTR_OUTER 2 +#define TM_STMT_ATTR_ATOMIC 4 +#define TM_STMT_ATTR_RELAXED 8 + +extern int parse_tm_stmt_attr (tree, int); + +/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these + are ordered specifically such that more restrictive attributes are + at lower bit positions. This fact is known by the C++ tm attribute + inheritance code such that least bit extraction (mask & -mask) results + in the most restrictive attribute. */ +#define TM_ATTR_SAFE 1 +#define TM_ATTR_CALLABLE 2 +#define TM_ATTR_PURE 4 +#define TM_ATTR_IRREVOCABLE 8 +#define TM_ATTR_MAY_CANCEL_OUTER 16 + +extern int tm_attr_to_mask (tree); +extern tree tm_mask_to_attr (int); +extern tree find_tm_attribute (tree); + +/* A suffix-identifier value doublet that represents user-defined literals + for C++-0x. */ +enum overflow_type { + OT_UNDERFLOW = -1, + OT_NONE, + OT_OVERFLOW +}; + +struct GTY(()) tree_userdef_literal { + struct tree_base base; + tree suffix_id; + tree value; + tree num_string; + enum overflow_type overflow; +}; + +#define USERDEF_LITERAL_SUFFIX_ID(NODE) \ + (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id) + +#define USERDEF_LITERAL_VALUE(NODE) \ + (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value) + +#define USERDEF_LITERAL_OVERFLOW(NODE) \ + (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow) + +#define USERDEF_LITERAL_NUM_STRING(NODE) \ + (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string) + +#define USERDEF_LITERAL_TYPE(NODE) \ + (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE))) + +extern tree build_userdef_literal (tree suffix_id, tree value, + enum overflow_type overflow, + tree num_string); + +extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree); + +/* Possibe cases of scalar_to_vector conversion. */ +enum stv_conv { + stv_error, /* Error occured. */ + stv_nothing, /* Nothing happened. */ + stv_firstarg, /* First argument must be expanded. */ + stv_secondarg /* Second argument must be expanded. */ +}; + +extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code, + tree op0, tree op1, bool); + #endif /* ! GCC_C_COMMON_H */ --- gcc/c-family/c-pragma.h.jj 2013-06-12 14:59:07.000000000 +0200 +++ gcc/c-family/c-pragma.h 2013-06-13 12:06:51.105442359 +0200 @@ -36,6 +36,9 @@ typedef enum pragma_kind { PRAGMA_OMP_DECLARE_SIMD, PRAGMA_OMP_DECLARE_TARGET, PRAGMA_OMP_DISTRIBUTE, + PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR, + PRAGMA_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD, + PRAGMA_OMP_DISTRIBUTE_SIMD, PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, @@ -52,6 +55,10 @@ typedef enum pragma_kind { PRAGMA_OMP_SINGLE, PRAGMA_OMP_TARGET, PRAGMA_OMP_TARGET_DATA, + PRAGMA_OMP_TARGET_TEAMS, + PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE, + PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR, + PRAGMA_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD, PRAGMA_OMP_TARGET_UPDATE, PRAGMA_OMP_TASK, PRAGMA_OMP_TASKGROUP, @@ -59,6 +66,9 @@ typedef enum pragma_kind { PRAGMA_OMP_TASKYIELD, PRAGMA_OMP_THREADPRIVATE, PRAGMA_OMP_TEAMS, + PRAGMA_OMP_TEAMS_DISTRIBUTE, + PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR, + PRAGMA_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD, PRAGMA_GCC_PCH_PREPROCESS, --- gcc/c-family/c-omp.c.jj 2013-05-09 17:06:21.000000000 +0200 +++ gcc/c-family/c-omp.c 2013-06-14 12:43:47.381336138 +0200 @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. #include "coretypes.h" #include "tree.h" #include "c-common.h" +#include "c-pragma.h" #include "gimple.h" /* For create_tmp_var_raw. */ #include "langhooks.h" @@ -585,21 +586,55 @@ c_finish_omp_for (location_t locus, enum } } - -/* Divide CLAUSES into two lists: those that apply to a parallel - construct, and those that apply to a work-sharing construct. Place - the results in *PAR_CLAUSES and *WS_CLAUSES respectively. In - addition, add a nowait clause to the work-sharing list. LOC is the - location of the OMP_PARALLEL*. */ +/* Right now we have 14 different combined constructs, this + function attempts to split or duplicate clauses for combined + constructs. CODE is the innermost construct in the combined construct, + and MASK allows to determine which constructs are combined together, + as every construct has at least one clause that no other construct + has (except for OMP_SECTIONS, but that can be only combined with parallel). + Combined constructs are: + #pragma omp parallel for + #pragma omp parallel sections + #pragma omp parallel for simd + #pragma omp for simd + #pragma omp distribute simd + #pragma omp distribute parallel for + #pragma omp distribute parallel for simd + #pragma omp teams distribute + #pragma omp teams distribute parallel for + #pragma omp teams distribute parallel for simd + #pragma omp target teams + #pragma omp target teams distribute + #pragma omp target teams distribute parallel for + #pragma omp target teams distribute parallel for simd */ void -c_split_parallel_clauses (location_t loc, tree clauses, - tree *par_clauses, tree *ws_clauses) +c_omp_split_clauses (location_t loc, enum tree_code code, + omp_clause_mask mask, tree clauses, tree *cclauses) { - tree next; + tree next, c; + enum c_omp_clause_split s; + int i; - *par_clauses = NULL; - *ws_clauses = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); + for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++) + cclauses[i] = NULL; + /* Add implicit nowait clause on + #pragma omp parallel {for,for simd,sections}. */ + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + switch (code) + { + case OMP_FOR: + case OMP_SIMD: + cclauses[C_OMP_CLAUSE_SPLIT_FOR] + = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); + break; + case OMP_SECTIONS: + cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS] + = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); + break; + default: + break; + } for (; clauses ; clauses = next) { @@ -607,36 +642,228 @@ c_split_parallel_clauses (location_t loc switch (OMP_CLAUSE_CODE (clauses)) { - case OMP_CLAUSE_PRIVATE: - case OMP_CLAUSE_SHARED: - case OMP_CLAUSE_FIRSTPRIVATE: - case OMP_CLAUSE_LASTPRIVATE: - case OMP_CLAUSE_REDUCTION: + /* First the clauses that are unique to some constructs. */ + case OMP_CLAUSE_DEVICE: + case OMP_CLAUSE_MAP: + s = C_OMP_CLAUSE_SPLIT_TARGET; + break; + case OMP_CLAUSE_NUM_TEAMS: + case OMP_CLAUSE_THREAD_LIMIT: + s = C_OMP_CLAUSE_SPLIT_TEAMS; + break; + case OMP_CLAUSE_DIST_SCHEDULE: + s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; + break; case OMP_CLAUSE_COPYIN: - case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: - case OMP_CLAUSE_DEFAULT: case OMP_CLAUSE_PROC_BIND: - OMP_CLAUSE_CHAIN (clauses) = *par_clauses; - *par_clauses = clauses; + s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; - - case OMP_CLAUSE_SCHEDULE: case OMP_CLAUSE_ORDERED: - case OMP_CLAUSE_COLLAPSE: + case OMP_CLAUSE_SCHEDULE: + case OMP_CLAUSE_NOWAIT: + s = C_OMP_CLAUSE_SPLIT_FOR; + break; case OMP_CLAUSE_SAFELEN: - case OMP_CLAUSE_ALIGNED: case OMP_CLAUSE_LINEAR: - OMP_CLAUSE_CHAIN (clauses) = *ws_clauses; - *ws_clauses = clauses; + case OMP_CLAUSE_ALIGNED: + s = C_OMP_CLAUSE_SPLIT_SIMD; + break; + /* Duplicate this to all of distribute, for and simd. */ + case OMP_CLAUSE_COLLAPSE: + if (code == OMP_SIMD) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_COLLAPSE); + OMP_CLAUSE_COLLAPSE_EXPR (c) + = OMP_CLAUSE_COLLAPSE_EXPR (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; + cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c; + } + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + { + if (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_COLLAPSE); + OMP_CLAUSE_COLLAPSE_EXPR (c) + = OMP_CLAUSE_COLLAPSE_EXPR (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; + cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c; + s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; + } + else + s = C_OMP_CLAUSE_SPLIT_FOR; + } + else + s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; + break; + /* Private clause is supported on all constructs but target, + it is enough to put it on the innermost one. For + #pragma omp {for,sections} put it on parallel though, + as that's what we did for OpenMP 3.1. */ + case OMP_CLAUSE_PRIVATE: + switch (code) + { + case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break; + case OMP_FOR: case OMP_SECTIONS: + case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; + case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; + case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break; + default: gcc_unreachable (); + } + break; + /* Firstprivate clause is supported on all constructs but + target and simd. Put it on the outermost of those and + duplicate on parallel. */ + case OMP_CLAUSE_FIRSTPRIVATE: + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + { + if (mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) + | (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c; + if (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) + s = C_OMP_CLAUSE_SPLIT_TEAMS; + else + s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; + } + else + /* This must be + #pragma omp parallel{, for{, simd}, sections}. */ + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + } + else if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) + { + /* This must be #pragma omp {,target }teams distribute. */ + gcc_assert (code == OMP_DISTRIBUTE); + s = C_OMP_CLAUSE_SPLIT_TEAMS; + } + else if (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) + { + /* This must be #pragma omp distribute simd. */ + gcc_assert (code == OMP_SIMD); + s = C_OMP_CLAUSE_SPLIT_TEAMS; + } + else + { + /* This must be #pragma omp for simd. */ + gcc_assert (code == OMP_SIMD); + s = C_OMP_CLAUSE_SPLIT_FOR; + } + break; + /* Lastprivate is allowed on for, sections and simd. In + parallel {for{, simd},sections} we actually want to put it on + parallel rather than for or sections. */ + case OMP_CLAUSE_LASTPRIVATE: + if (code == OMP_FOR || code == OMP_SECTIONS) + { + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else + s = C_OMP_CLAUSE_SPLIT_FOR; + break; + } + gcc_assert (code == OMP_SIMD); + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_LASTPRIVATE); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else + s = C_OMP_CLAUSE_SPLIT_FOR; + OMP_CLAUSE_CHAIN (c) = cclauses[s]; + cclauses[s] = c; + } + s = C_OMP_CLAUSE_SPLIT_SIMD; + break; + /* Shared and default clauses are allowed on private and teams. */ + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_DEFAULT: + if (code == OMP_TEAMS) + { + s = C_OMP_CLAUSE_SPLIT_TEAMS; + break; + } + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_CODE (clauses)); + if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED) + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + else + OMP_CLAUSE_DEFAULT_KIND (c) + = OMP_CLAUSE_DEFAULT_KIND (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; + + } + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + break; + /* Reduction is allowed on simd, for, parallel, sections and teams. + Duplicate it on all of them, but omit on for or sections if + parallel is present. */ + case OMP_CLAUSE_REDUCTION: + if (code == OMP_SIMD) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_REDUCTION); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_REDUCTION_CODE (c) + = OMP_CLAUSE_REDUCTION_CODE (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; + cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c; + } + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) + { + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_REDUCTION); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_REDUCTION_CODE (c) + = OMP_CLAUSE_REDUCTION_CODE (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c; + s = C_OMP_CLAUSE_SPLIT_TEAMS; + } + else if (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else + s = C_OMP_CLAUSE_SPLIT_FOR; + } + else if (code == OMP_SECTIONS) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else + s = C_OMP_CLAUSE_SPLIT_TEAMS; + break; + case OMP_CLAUSE_IF: + /* FIXME: This is currently being discussed. */ + if (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else + s = C_OMP_CLAUSE_SPLIT_TARGET; break; - default: gcc_unreachable (); } + OMP_CLAUSE_CHAIN (clauses) = cclauses[s]; + cclauses[s] = clauses; } } + /* qsort callback to compare #pragma omp declare simd clauses. */ static int