From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 102225 invoked by alias); 26 Jun 2015 13:32:34 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 102209 invoked by uid 89); 26 Jun 2015 13:32:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL,BAYES_50,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 26 Jun 2015 13:32:27 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 30E6DC2FF3 for ; Fri, 26 Jun 2015 13:32:26 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-82.ams2.redhat.com [10.36.116.82]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t5QDWOrw027278 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 26 Jun 2015 09:32:25 -0400 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.14.9/8.14.9) with ESMTP id t5QDWMob011114 for ; Fri, 26 Jun 2015 15:32:22 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.14.9/8.14.9/Submit) id t5QDWLWV011113 for gcc-patches@gcc.gnu.org; Fri, 26 Jun 2015 15:32:21 +0200 Date: Fri, 26 Jun 2015 13:38:00 -0000 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [gomp4.1] Add support for non-static data member iterators Message-ID: <20150626133221.GT10247@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes X-SW-Source: 2015-06/txt/msg01954.txt.bz2 Hi! As private/lastprivate/linear clauses now allow non-static data members in C++, it (unfortunately) means that also the iterator variables of distribute/for/simd/taskloop loops can be non-static data members. This patch implements it; tested on x86_64-linux, committed to gomp-4_1-branch. 2015-06-26 Jakub Jelinek * gimplify.c (enum omp_region_type): Add ORT_NONE. (gimplify_bind_expr, omp_firstprivatize_variable, omp_add_variable, omp_notice_variable): Handle ORT_NONE. (gimplify_omp_for): For OMP_FOR_PRE_BODY of taskloop, temporarily switch on ORT_NONE gimplify_omp_ctxp if it is NULL. gcc/cp/ * cp-tree.h (push_omp_privatization_clauses): Add bool argument. (omp_privatize_field): New prototype. * parser.c (cp_parser_omp_for_incr): For processing_template_decl use cp_tree_equals. (cp_parser_omp_for_loop_init): Change return type to tree, handle non-static data member iterators, return decl to add to private clause if one should be added. (cp_parser_omp_for_loop): Adjust caller. For OMP_SIMD, add OMP_CLAUSE_LINEAR or OMP_CLAUSE_LASTPRIVATE instead of OMP_CLAUSE_PRIVATE. Handle NULL TREE_TYPE as non-pointer. (cp_parser_pragma): Adjust push_omp_privatization_clauses callers. * pt.c (tsubst_omp_clauses): If there is a single OMP_CLAUSE_LINEAR with NULL OMP_CLAUSE_LINEAR_STEP, make sure it is NULL even after finish_omp_clauses. (omp_parallel_combined_clauses): New variable. (tsubst_omp_for_iterator): Handle non-static data members, for combined parallel for move lastprivate clause from parallel to for and avoid making already private iterator private again. (tsubst_expr): Adjust push_omp_privatization_clauses callers. For OMP_PARALLEL with OMP_PARALLEL_COMBINED temporarily set omp_parallel_combined_clauses and clear it in OMP_FOR and OMP_SECTIONS. (instantiate_decl): Call save_omp_privatization_clauses and restore_omp_privatization_clauses if nested. (dependent_omp_for_p): Return true even if the iterator is non-type dependent SCOPE_REF. * semantics.c (omp_private_member_ignore_next): New variable. (omp_privatize_field): No longer static. (push_omp_privatization_clauses): Add ignore_next argument. Set omp_private_member_ignore_next to it, return NULL early if omp_private_member_ignore_next was set before. (pop_omp_privatization_clauses): Do nothing if stmt is NULL. (save_omp_privatization_clauses): Save also omp_private_member_ignore_next flag in the vector. (restore_omp_privatization_clauses): And restore it. (finish_omp_for): For OMP_SIMD, fill in OMP_CLAUSE_LINEAR_STEP for the iterator if NULL. libgomp/ * testsuite/libgomp.c++/member-1.C: Remove dg-options. * testsuite/libgomp.c++/member-2.C: Remove dg-options. * testsuite/libgomp.c++/member-3.C: New test. * testsuite/libgomp.c++/member-4.C: New test. * testsuite/libgomp.c++/member-5.C: New test. --- gcc/gimplify.c.jj 2015-06-24 12:04:02.000000000 +0200 +++ gcc/gimplify.c 2015-06-25 19:14:25.994242855 +0200 @@ -121,7 +121,10 @@ enum omp_region_type /* Data region. */ ORT_TARGET_DATA = 16, /* Data region with offloading. */ - ORT_TARGET = 32 + ORT_TARGET = 32, + /* Dummy OpenMP region, used to disable expansion of + DECL_VALUE_EXPRs in taskloop pre body. */ + ORT_NONE = 64 }; /* Gimplify hashtable helper. */ @@ -1083,7 +1086,7 @@ gimplify_bind_expr (tree *expr_p, gimple struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; /* Mark variable as local. */ - if (ctx && !DECL_EXTERNAL (t) + if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t) && (! DECL_SEEN_IN_BIND_EXPR_P (t) || splay_tree_lookup (ctx->variables, (splay_tree_key) t) == NULL)) @@ -5554,7 +5557,7 @@ omp_firstprivatize_variable (struct gimp { splay_tree_node n; - if (decl == NULL || !DECL_P (decl)) + if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE) return; do @@ -5646,7 +5649,7 @@ omp_add_variable (struct gimplify_omp_ct unsigned int nflags; tree t; - if (error_operand_p (decl)) + if (error_operand_p (decl) || ctx->region_type == ORT_NONE) return; /* Never elide decls whose type has TREE_ADDRESSABLE set. This means @@ -5799,6 +5802,9 @@ omp_notice_variable (struct gimplify_omp if (error_operand_p (decl)) return false; + if (ctx->region_type == ORT_NONE) + return lang_hooks.decls.omp_disregard_value_expr (decl, false); + /* Threadprivate variables are predetermined. */ if (is_global_var (decl)) { @@ -7195,7 +7201,20 @@ gimplify_omp_for (tree *expr_p, gimple_s } } } - gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body); + if (OMP_FOR_PRE_BODY (for_stmt)) + { + if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp) + gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body); + else + { + struct gimplify_omp_ctx ctx; + memset (&ctx, 0, sizeof (ctx)); + ctx.region_type = ORT_NONE; + gimplify_omp_ctxp = &ctx; + gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body); + gimplify_omp_ctxp = NULL; + } + } OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE; if (OMP_FOR_INIT (for_stmt) == NULL_TREE) --- gcc/cp/cp-tree.h.jj 2015-06-17 21:21:16.000000000 +0200 +++ gcc/cp/cp-tree.h 2015-06-25 17:31:50.677516397 +0200 @@ -5999,7 +5999,7 @@ extern tree omp_reduction_id (enum tre extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *); extern void cp_check_omp_declare_reduction (tree); extern tree finish_omp_clauses (tree, bool); -extern tree push_omp_privatization_clauses (void); +extern tree push_omp_privatization_clauses (bool); extern void pop_omp_privatization_clauses (tree); extern void save_omp_privatization_clauses (vec &); extern void restore_omp_privatization_clauses (vec &); @@ -6025,6 +6025,7 @@ extern void finish_omp_taskwait (void) extern void finish_omp_taskyield (void); extern void finish_omp_cancel (tree); extern void finish_omp_cancellation_point (tree); +extern tree omp_privatize_field (tree); extern tree begin_transaction_stmt (location_t, tree *, int); extern void finish_transaction_stmt (tree, tree, int, tree); extern tree build_transaction_expr (location_t, tree, int, tree); --- gcc/cp/parser.c.jj 2015-06-22 14:30:25.000000000 +0200 +++ gcc/cp/parser.c 2015-06-25 17:58:29.649322440 +0200 @@ -30538,13 +30538,15 @@ cp_parser_omp_for_incr (cp_parser *parse ? PREINCREMENT_EXPR : PREDECREMENT_EXPR); cp_lexer_consume_token (parser->lexer); lhs = cp_parser_simple_cast_expression (parser); - if (lhs != decl) + if (lhs != decl + && (!processing_template_decl || !cp_tree_equal (lhs, decl))) return error_mark_node; return build2 (op, TREE_TYPE (decl), decl, NULL_TREE); } lhs = cp_parser_primary_expression (parser, false, false, false, &idk); - if (lhs != decl) + if (lhs != decl + && (!processing_template_decl || !cp_tree_equal (lhs, decl))) return error_mark_node; token = cp_lexer_peek_token (parser->lexer); @@ -30570,7 +30572,8 @@ cp_parser_omp_for_incr (cp_parser *parse lhs = cp_parser_binary_expression (parser, false, false, PREC_ADDITIVE_EXPRESSION, NULL); token = cp_lexer_peek_token (parser->lexer); - decl_first = lhs == decl; + decl_first = (lhs == decl + || (processing_template_decl && cp_tree_equal (lhs, decl))); if (decl_first) lhs = NULL_TREE; if (token->type != CPP_PLUS @@ -30603,7 +30606,9 @@ cp_parser_omp_for_incr (cp_parser *parse if (!decl_first) { - if (rhs != decl || op == MINUS_EXPR) + if ((rhs != decl + && (!processing_template_decl || !cp_tree_equal (rhs, decl))) + || op == MINUS_EXPR) return error_mark_node; rhs = build2 (op, TREE_TYPE (decl), lhs, decl); } @@ -30619,7 +30624,7 @@ cp_parser_omp_for_incr (cp_parser *parse Return true if the resulting construct should have an OMP_CLAUSE_PRIVATE added to it. */ -static bool +static tree cp_parser_omp_for_loop_init (cp_parser *parser, enum tree_code code, tree &this_pre_body, @@ -30629,9 +30634,9 @@ cp_parser_omp_for_loop_init (cp_parser * tree &real_decl) { if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) - return false; + return NULL_TREE; - bool add_private_clause = false; + tree add_private_clause = NULL_TREE; /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too): @@ -30762,6 +30767,33 @@ cp_parser_omp_for_loop_init (cp_parser * cp_parser_parse_tentatively (parser); decl = cp_parser_primary_expression (parser, false, false, false, &idk); + cp_token *last_tok = cp_lexer_peek_token (parser->lexer); + if (!cp_parser_error_occurred (parser) + && decl + && (TREE_CODE (decl) == COMPONENT_REF + || (TREE_CODE (decl) == SCOPE_REF && TREE_TYPE (decl)))) + { + cp_parser_abort_tentative_parse (parser); + cp_parser_parse_tentatively (parser); + cp_token *token = cp_lexer_peek_token (parser->lexer); + tree name = cp_parser_id_expression (parser, /*template_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false, + /*optional_p=*/false); + if (name != error_mark_node + && last_tok == cp_lexer_peek_token (parser->lexer)) + { + decl = cp_parser_lookup_name_simple (parser, name, + token->location); + if (TREE_CODE (decl) == FIELD_DECL) + add_private_clause = omp_privatize_field (decl); + } + cp_parser_abort_tentative_parse (parser); + cp_parser_parse_tentatively (parser); + decl = cp_parser_primary_expression (parser, false, false, + false, &idk); + } if (!cp_parser_error_occurred (parser) && decl && DECL_P (decl) @@ -30776,7 +30808,8 @@ cp_parser_omp_for_loop_init (cp_parser * decl, NOP_EXPR, rhs, tf_warning_or_error)); - add_private_clause = true; + if (!add_private_clause) + add_private_clause = decl; } else { @@ -30824,7 +30857,7 @@ cp_parser_omp_for_loop (cp_parser *parse for (i = 0; i < collapse; i++) { int bracecount = 0; - bool add_private_clause = false; + tree add_private_clause = NULL_TREE; location_t loc; if (code != CILK_FOR @@ -30848,9 +30881,9 @@ cp_parser_omp_for_loop (cp_parser *parse this_pre_body = push_stmt_list (); add_private_clause - |= cp_parser_omp_for_loop_init (parser, code, - this_pre_body, for_block, - init, decl, real_decl); + = cp_parser_omp_for_loop_init (parser, code, + this_pre_body, for_block, + init, decl, real_decl); cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); if (this_pre_body) @@ -30899,13 +30932,13 @@ cp_parser_omp_for_loop (cp_parser *parse OMP_CLAUSE_CHAIN (l) = clauses; clauses = l; } - add_private_clause = false; + add_private_clause = NULL_TREE; } else { if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE && OMP_CLAUSE_DECL (*c) == real_decl) - add_private_clause = false; + add_private_clause = NULL_TREE; c = &OMP_CLAUSE_CHAIN (*c); } } @@ -30931,13 +30964,22 @@ cp_parser_omp_for_loop (cp_parser *parse } if (c == NULL) { - c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE); - OMP_CLAUSE_DECL (c) = decl; - c = finish_omp_clauses (c, false); + if (code != OMP_SIMD) + c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE); + else if (collapse == 1) + c = build_omp_clause (loc, OMP_CLAUSE_LINEAR); + else + c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE); + OMP_CLAUSE_DECL (c) = add_private_clause; + c = finish_omp_clauses (c, true); if (c) { OMP_CLAUSE_CHAIN (c) = clauses; clauses = c; + /* For linear, signal that we need to fill up + the so far unknown linear step. */ + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR) + OMP_CLAUSE_LINEAR_STEP (c) = NULL_TREE; } } } @@ -30954,7 +30996,8 @@ cp_parser_omp_for_loop (cp_parser *parse until finish_omp_for. */ if (real_decl && ((processing_template_decl - && !POINTER_TYPE_P (TREE_TYPE (real_decl))) + && (TREE_TYPE (real_decl) == NULL_TREE + || !POINTER_TYPE_P (TREE_TYPE (real_decl)))) || CLASS_TYPE_P (TREE_TYPE (real_decl)))) incr = cp_parser_omp_for_incr (parser, real_decl); else @@ -33876,19 +33919,19 @@ cp_parser_pragma (cp_parser *parser, enu case PRAGMA_OMP_TEAMS: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; - stmt = push_omp_privatization_clauses (); + stmt = push_omp_privatization_clauses (false); cp_parser_omp_construct (parser, pragma_tok); pop_omp_privatization_clauses (stmt); return true; case PRAGMA_OMP_ORDERED: - stmt = push_omp_privatization_clauses (); + stmt = push_omp_privatization_clauses (false); ret = cp_parser_omp_ordered (parser, pragma_tok, context); pop_omp_privatization_clauses (stmt); return ret; case PRAGMA_OMP_TARGET: - stmt = push_omp_privatization_clauses (); + stmt = push_omp_privatization_clauses (false); ret = cp_parser_omp_target (parser, pragma_tok, context); pop_omp_privatization_clauses (stmt); return ret; @@ -33932,7 +33975,7 @@ cp_parser_pragma (cp_parser *parser, enu "%<#pragma simd%> must be inside a function"); break; } - stmt = push_omp_privatization_clauses (); + stmt = push_omp_privatization_clauses (false); cp_parser_cilk_simd (parser, pragma_tok); pop_omp_privatization_clauses (stmt); return true; --- gcc/cp/pt.c.jj 2015-06-18 10:57:22.000000000 +0200 +++ gcc/cp/pt.c 2015-06-26 13:07:29.931105279 +0200 @@ -13528,7 +13528,8 @@ static tree tsubst_omp_clauses (tree clauses, bool declare_simd, bool allow_fields, tree args, tsubst_flags_t complain, tree in_decl) { - tree new_clauses = NULL, nc, oc; + tree new_clauses = NULL_TREE, nc, oc; + tree linear_no_step = NULL_TREE; for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc)) { @@ -13609,6 +13610,12 @@ tsubst_omp_clauses (tree clauses, bool d OMP_CLAUSE_OPERAND (nc, 1) = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain, in_decl, /*integral_constant_expression_p=*/false); + if (OMP_CLAUSE_CODE (oc) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE) + { + gcc_assert (!linear_no_step); + linear_no_step = nc; + } break; case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_DEFAULT: @@ -13688,7 +13695,16 @@ tsubst_omp_clauses (tree clauses, bool d new_clauses = nreverse (new_clauses); if (!declare_simd) - new_clauses = finish_omp_clauses (new_clauses, allow_fields); + { + new_clauses = finish_omp_clauses (new_clauses, allow_fields); + if (linear_no_step) + for (nc = new_clauses; nc; nc = OMP_CLAUSE_CHAIN (nc)) + if (nc == linear_no_step) + { + OMP_CLAUSE_LINEAR_STEP (nc) = NULL_TREE; + break; + } + } return new_clauses; } @@ -13735,6 +13751,12 @@ tsubst_copy_asm_operands (tree t, tree a #undef RECUR } +/* Used to temporarily communicate the list of #pragma omp parallel + clauses to #pragma omp for instantiation if they are combined + together. */ + +static tree *omp_parallel_combined_clauses; + /* Substitute one OMP_FOR iterator. */ static void @@ -13763,7 +13785,41 @@ tsubst_omp_for_iterator (tree t, int i, decl = tsubst_decl (decl, args, complain); } else - decl = RECUR (decl); + { + if (TREE_CODE (decl) == SCOPE_REF) + { + decl = RECUR (decl); + if (TREE_CODE (decl) == COMPONENT_REF) + { + tree v = decl; + while (v) + switch (TREE_CODE (v)) + { + case COMPONENT_REF: + case MEM_REF: + case INDIRECT_REF: + CASE_CONVERT: + case POINTER_PLUS_EXPR: + v = TREE_OPERAND (v, 0); + continue; + case PARM_DECL: + if (DECL_CONTEXT (v) == current_function_decl + && DECL_ARTIFICIAL (v) + && DECL_NAME (v) == this_identifier) + { + decl = TREE_OPERAND (decl, 1); + decl = omp_privatize_field (decl); + } + /* FALLTHRU */ + default: + v = NULL_TREE; + break; + } + } + } + else + decl = RECUR (decl); + } init = RECUR (init); tree auto_node = type_uses_auto (TREE_TYPE (decl)); @@ -13810,25 +13866,51 @@ tsubst_omp_for_iterator (tree t, int i, } else if (init) { - tree c; - for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c)) + tree *pc; + int j; + for (j = (omp_parallel_combined_clauses == NULL ? 1 : 0); j < 2; j++) { - if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) - && OMP_CLAUSE_DECL (c) == decl) + for (pc = j ? clauses : omp_parallel_combined_clauses; *pc; ) + { + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE + && OMP_CLAUSE_DECL (*pc) == decl) + break; + else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE + && OMP_CLAUSE_DECL (*pc) == decl) + { + if (j) + break; + /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ + tree c = *pc; + *pc = OMP_CLAUSE_CHAIN (c); + OMP_CLAUSE_CHAIN (c) = *clauses; + *clauses = c; + } + else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_FIRSTPRIVATE + && OMP_CLAUSE_DECL (*pc) == decl) + { + error ("iteration variable %qD should not be firstprivate", + decl); + *pc = OMP_CLAUSE_CHAIN (*pc); + } + else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_DECL (*pc) == decl) + { + error ("iteration variable %qD should not be reduction", + decl); + *pc = OMP_CLAUSE_CHAIN (*pc); + } + else + pc = &OMP_CLAUSE_CHAIN (*pc); + } + if (*pc) break; - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - && OMP_CLAUSE_DECL (c) == decl) - error ("iteration variable %qD should not be firstprivate", decl); - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_DECL (c) == decl) - error ("iteration variable %qD should not be reduction", decl); } - if (c == NULL) + if (*pc == NULL_TREE) { - c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); + tree c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); OMP_CLAUSE_DECL (c) = decl; - c = finish_omp_clauses (c, false); + c = finish_omp_clauses (c, true); if (c) { OMP_CLAUSE_CHAIN (c) = *clauses; @@ -14289,18 +14371,21 @@ tsubst_expr (tree t, tree args, tsubst_f break; case OMP_PARALLEL: - r = push_omp_privatization_clauses (); + r = push_omp_privatization_clauses (OMP_PARALLEL_COMBINED (t)); tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false, true, args, complain, in_decl); + if (OMP_PARALLEL_COMBINED (t)) + omp_parallel_combined_clauses = &tmp; stmt = begin_omp_parallel (); RECUR (OMP_PARALLEL_BODY (t)); + gcc_assert (omp_parallel_combined_clauses == NULL); OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt)) = OMP_PARALLEL_COMBINED (t); pop_omp_privatization_clauses (r); break; case OMP_TASK: - r = push_omp_privatization_clauses (); + r = push_omp_privatization_clauses (false); tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false, true, args, complain, in_decl); stmt = begin_omp_task (); @@ -14321,7 +14406,7 @@ tsubst_expr (tree t, tree args, tsubst_f tree incrv = NULL_TREE; int i; - r = push_omp_privatization_clauses (); + r = push_omp_privatization_clauses (OMP_FOR_INIT (t) == NULL_TREE); clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false, true, args, complain, in_decl); if (OMP_FOR_INIT (t) != NULL_TREE) @@ -14343,6 +14428,7 @@ tsubst_expr (tree t, tree args, tsubst_f tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv, &clauses, args, complain, in_decl, integral_constant_expression_p); + omp_parallel_combined_clauses = NULL; body = push_stmt_list (); RECUR (OMP_FOR_BODY (t)); @@ -14368,10 +14454,13 @@ tsubst_expr (tree t, tree args, tsubst_f break; case OMP_SECTIONS: + omp_parallel_combined_clauses = NULL; + /* FALLTHRU */ case OMP_SINGLE: case OMP_TEAMS: case OMP_CRITICAL: - r = push_omp_privatization_clauses (); + r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS + && OMP_TEAMS_COMBINED (t)); tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, true, args, complain, in_decl); stmt = push_stmt_list (); @@ -20270,7 +20359,7 @@ instantiate_decl (tree d, int defer_ok, bool external_p; bool deleted_p; tree fn_context; - bool nested; + bool nested = false; /* This function should only be used to instantiate templates for functions and static member variables. */ @@ -20492,6 +20581,10 @@ instantiate_decl (tree d, int defer_ok, fn_context = decl_function_context (d); nested = (current_function_decl != NULL_TREE); + vec omp_privatization_save; + if (nested) + save_omp_privatization_clauses (omp_privatization_save); + if (!fn_context) push_to_top_level (); else @@ -20661,6 +20754,8 @@ out: c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings; pop_deferring_access_checks (); pop_tinst_level (); + if (nested) + restore_omp_privatization_clauses (omp_privatization_save); timevar_pop (TV_TEMPLATE_INST); @@ -21999,7 +22094,8 @@ dependent_omp_for_p (tree declv, tree in tree cond = TREE_VEC_ELT (condv, i); tree incr = TREE_VEC_ELT (incrv, i); - if (type_dependent_expression_p (decl)) + if (type_dependent_expression_p (decl) + || TREE_CODE (decl) == SCOPE_REF) return true; if (init && type_dependent_expression_p (init)) --- gcc/cp/semantics.c.jj 2015-06-23 16:24:16.000000000 +0200 +++ gcc/cp/semantics.c 2015-06-25 17:28:25.399646095 +0200 @@ -70,6 +70,7 @@ static tree capture_decltype (tree); static hash_map *omp_private_member_map; static vec omp_private_member_vec; +static bool omp_private_member_ignore_next; /* Deferred Access Checking Overview @@ -4324,7 +4325,7 @@ omp_note_field_privatization (tree f, tr /* Privatize FIELD_DECL T, return corresponding DECL_OMP_PRIVATIZED_MEMBER dummy VAR_DECL. */ -static tree +tree omp_privatize_field (tree t) { tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); @@ -6517,8 +6518,14 @@ finish_omp_clauses (tree clauses, bool a privatization clauses for non-static data members. */ tree -push_omp_privatization_clauses (void) +push_omp_privatization_clauses (bool ignore_next) { + if (omp_private_member_ignore_next) + { + omp_private_member_ignore_next = ignore_next; + return NULL_TREE; + } + omp_private_member_ignore_next = ignore_next; if (omp_private_member_map) omp_private_member_vec.safe_push (error_mark_node); return push_stmt_list (); @@ -6530,6 +6537,8 @@ push_omp_privatization_clauses (void) void pop_omp_privatization_clauses (tree stmt) { + if (stmt == NULL_TREE) + return; stmt = pop_stmt_list (stmt); if (omp_private_member_map) { @@ -6563,8 +6572,12 @@ void save_omp_privatization_clauses (vec &save) { save = vNULL; + if (omp_private_member_ignore_next) + save.safe_push (integer_one_node); + omp_private_member_ignore_next = false; if (!omp_private_member_map) return; + while (!omp_private_member_vec.is_empty ()) { tree t = omp_private_member_vec.pop (); @@ -6594,8 +6607,16 @@ void restore_omp_privatization_clauses (vec &save) { gcc_assert (omp_private_member_vec.is_empty ()); + omp_private_member_ignore_next = false; if (save.is_empty ()) return; + if (save.length () == 1 && save[0] == integer_one_node) + { + omp_private_member_ignore_next = true; + save.release (); + return; + } + omp_private_member_map = new hash_map ; while (!save.is_empty ()) { @@ -6603,6 +6624,12 @@ restore_omp_privatization_clauses (vecget_or_insert (t); @@ -7323,6 +7350,68 @@ finish_omp_for (location_t locus, enum t } OMP_FOR_CLAUSES (omp_for) = clauses; + /* For simd loops with non-static data member iterators, we could have added + OMP_CLAUSE_LINEAR clauses without OMP_CLAUSE_LINEAR_STEP. As we know the + step at this point, fill it in. */ + if (code == OMP_SIMD && !processing_template_decl + && TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)) == 1) + for (tree c = find_omp_clause (clauses, OMP_CLAUSE_LINEAR); c; + c = find_omp_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_LINEAR)) + if (OMP_CLAUSE_LINEAR_STEP (c) == NULL_TREE) + { + decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0), 0); + gcc_assert (decl == OMP_CLAUSE_DECL (c)); + incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); + tree step, stept; + switch (TREE_CODE (incr)) + { + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + /* c_omp_for_incr_canonicalize_ptr() should have been + called to massage things appropriately. */ + gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl))); + OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1); + break; + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* c_omp_for_incr_canonicalize_ptr() should have been + called to massage things appropriately. */ + gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl))); + OMP_CLAUSE_LINEAR_STEP (c) + = build_int_cst (TREE_TYPE (decl), -1); + break; + case MODIFY_EXPR: + gcc_assert (TREE_OPERAND (incr, 0) == decl); + incr = TREE_OPERAND (incr, 1); + switch (TREE_CODE (incr)) + { + case PLUS_EXPR: + if (TREE_OPERAND (incr, 1) == decl) + step = TREE_OPERAND (incr, 0); + else + step = TREE_OPERAND (incr, 1); + break; + case MINUS_EXPR: + case POINTER_PLUS_EXPR: + gcc_assert (TREE_OPERAND (incr, 0) == decl); + step = TREE_OPERAND (incr, 1); + break; + default: + gcc_unreachable (); + } + stept = TREE_TYPE (decl); + if (POINTER_TYPE_P (stept)) + stept = sizetype; + step = fold_convert (stept, step); + if (TREE_CODE (incr) == MINUS_EXPR) + step = fold_build1 (NEGATE_EXPR, stept, step); + OMP_CLAUSE_LINEAR_STEP (c) = step; + break; + default: + gcc_unreachable (); + } + } + if (block) { tree omp_par = make_node (OMP_PARALLEL); --- libgomp/testsuite/libgomp.c++/member-1.C.jj 2015-06-03 09:45:48.000000000 +0200 +++ libgomp/testsuite/libgomp.c++/member-1.C 2015-06-25 11:17:21.588886636 +0200 @@ -1,5 +1,4 @@ // { dg-do run } -// { dg-options "-O2 -fopenmp" } #include --- libgomp/testsuite/libgomp.c++/member-2.C.jj 2015-06-03 09:46:46.000000000 +0200 +++ libgomp/testsuite/libgomp.c++/member-2.C 2015-06-25 11:17:29.656761918 +0200 @@ -1,5 +1,4 @@ // { dg-do run } -// { dg-options "-O2 -fopenmp" } #include --- libgomp/testsuite/libgomp.c++/member-3.C.jj 2015-06-25 11:17:07.708101213 +0200 +++ libgomp/testsuite/libgomp.c++/member-3.C 2015-06-25 18:17:15.924234255 +0200 @@ -0,0 +1,105 @@ +// { dg-do run } + +struct R { R () {}; ~R () {}; int r; }; +struct T { T () {}; virtual ~T () {}; int t; }; +int c; +struct A : public R, virtual public T { A () : b(c) {} int a; int &b; void m1 (); }; +int d[64]; + +void +A::m1 () +{ + r = 0; + #pragma omp parallel for private (a) reduction(|:R::r) + for (a = 0; A::a < 31; a += 2) + r |= (1 << A::a); + if (r != 0x55555555) + __builtin_abort (); + #pragma omp parallel for simd linear (R::r) + for (R::r = 0; r < 32; R::r++) + d[r + 8] |= 1; + for (int i = 0; i < 64; i++) + if (d[i] != ((i >= 8 && i < 32 + 8) ? 1 : 0)) + __builtin_abort (); + #pragma omp parallel for lastprivate (t) + for (T::t = 0; t < 32; t += 3) + d[T::t + 2] |= 2; + if (T::t != 33) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0))) + __builtin_abort (); + #pragma omp simd linear (t) + for (t = 0; t < 32; t++) + d[T::t + 9] |= 4; + if (t != 32) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0))) + __builtin_abort (); + r = 0; + #pragma omp parallel for reduction(|:r) + for (a = 0; A::a < 31; a += 2) + r |= (1 << A::a); + if (r != 0x55555555) + __builtin_abort (); + #pragma omp parallel for simd + for (R::r = 0; r < 32; R::r += 2) + d[r + 8] |= 8; + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0))) + __builtin_abort (); + #pragma omp simd collapse(2) + for (T::t = 0; t < 7; t += 2) + for (a = 0; A::a < 8; a++) + d[((t << 2) | a) + 3] |= 16; + if (t != 8 || A::a != 8) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? 16 : 0))) + __builtin_abort (); + T::t = 32; + a = 16; + #pragma omp parallel + #pragma omp single + #pragma omp taskloop simd collapse(2) + for (t = 0; T::t < 7; T::t += 2) + for (A::a = 0; a < 8; A::a++) + d[((t << 2) | A::a) + 3] |= 32; + if (T::t != 8 || a != 8) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0))) + __builtin_abort (); + #pragma omp parallel + #pragma omp single + #pragma omp taskloop simd + for (R::r = 0; r < 31; R::r += 2) + d[r + 8] |= 64; + if (r != 32) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (64 | 8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0))) + __builtin_abort (); +} + +int +main () +{ + A a; + a.m1 (); +} --- libgomp/testsuite/libgomp.c++/member-4.C.jj 2015-06-25 17:54:13.264212461 +0200 +++ libgomp/testsuite/libgomp.c++/member-4.C 2015-06-25 18:17:28.981036156 +0200 @@ -0,0 +1,108 @@ +// { dg-do run } + +int c, d, e; +struct R { R () {}; ~R () {}; int r; }; +template +struct T { T () : t(d) {}; virtual ~T () {}; Q t; }; +template +struct A : public R, virtual public T { A () : b(c), a(e) {} Q a; int &b; void m1 (); }; +int f[64]; + +template +void +A::m1 () +{ + r = 0; + #pragma omp parallel for private (a) reduction(|:R::r) + for (a = 0; A::a < 31; a += 2) + r |= (1 << A::a); + if (r != 0x55555555) + __builtin_abort (); + #pragma omp parallel for simd linear (R::r) + for (R::r = 0; r < 32; R::r++) + f[r + 8] |= 1; + for (int i = 0; i < 64; i++) + if (f[i] != ((i >= 8 && i < 32 + 8) ? 1 : 0)) + __builtin_abort (); + #pragma omp parallel for lastprivate (T::t) + for (T::t = 0; T::t < 32; T::t += 3) + f[T::t + 2] |= 2; + if (T::t != 33) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0))) + __builtin_abort (); + #pragma omp simd linear (T::t) + for (T::t = 0; T::t < 32; T::t++) + f[T::t + 9] |= 4; + if (T::t != 32) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0))) + __builtin_abort (); + r = 0; + #pragma omp parallel for reduction(|:r) + for (a = 0; A::a < 31; a += 2) + r |= (1 << A::a); + if (r != 0x55555555) + __builtin_abort (); + #pragma omp parallel for simd + for (R::r = 0; r < 32; R::r += 2) + f[r + 8] |= 8; + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0))) + __builtin_abort (); + #pragma omp simd collapse(2) + for (T::t = 0; T::t < 7; T::t += 2) + for (a = 0; A::a < 8; a++) + f[((T::t << 2) | a) + 3] |= 16; + if (T::t != 8 || A::a != 8) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? 16 : 0))) + __builtin_abort (); + T::t = 32; + a = 16; + #pragma omp parallel + #pragma omp single + #pragma omp taskloop simd collapse(2) + for (T::t = 0; T::t < 7; T::t += 2) + for (A::a = 0; a < 8; A::a++) + f[((T::t << 2) | A::a) + 3] |= 32; + if (T::t != 8 || a != 8) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0))) + __builtin_abort (); + #pragma omp parallel + #pragma omp single + #pragma omp taskloop simd + for (R::r = 0; r < 31; R::r += 2) + f[r + 8] |= 64; + if (r != 32) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (64 | 8 | 1)) : 0) + | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0) + | ((i >= 9 && i < 32 + 9) ? 4 : 0) + | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0))) + __builtin_abort (); +} + +int +main () +{ + A a; + a.m1 (); +} --- libgomp/testsuite/libgomp.c++/member-5.C.jj 2015-06-26 12:41:13.018061723 +0200 +++ libgomp/testsuite/libgomp.c++/member-5.C 2015-06-26 10:18:10.000000000 +0200 @@ -0,0 +1,183 @@ +// { dg-do run } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; + +template +class I +{ +public: + typedef ptrdiff_t difference_type; + I (); + ~I (); + I (T *); + I (const I &); + T &operator * (); + T *operator -> (); + T &operator [] (const difference_type &) const; + I &operator = (const I &); + I &operator ++ (); + I operator ++ (int); + I &operator -- (); + I operator -- (int); + I &operator += (const difference_type &); + I &operator -= (const difference_type &); + I operator + (const difference_type &) const; + I operator - (const difference_type &) const; + template friend bool operator == (I &, I &); + template friend bool operator == (const I &, const I &); + template friend bool operator < (I &, I &); + template friend bool operator < (const I &, const I &); + template friend bool operator <= (I &, I &); + template friend bool operator <= (const I &, const I &); + template friend bool operator > (I &, I &); + template friend bool operator > (const I &, const I &); + template friend bool operator >= (I &, I &); + template friend bool operator >= (const I &, const I &); + template friend typename I::difference_type operator - (I &, I &); + template friend typename I::difference_type operator - (const I &, const I &); + template friend I operator + (typename I::difference_type , const I &); +private: + T *p; +}; +template I::I () : p (0) {} +template I::~I () {} +template I::I (T *x) : p (x) {} +template I::I (const I &x) : p (x.p) {} +template T &I::operator * () { return *p; } +template T *I::operator -> () { return p; } +template T &I::operator [] (const difference_type &x) const { return p[x]; } +template I &I::operator = (const I &x) { p = x.p; return *this; } +template I &I::operator ++ () { ++p; return *this; } +template I I::operator ++ (int) { return I (p++); } +template I &I::operator -- () { --p; return *this; } +template I I::operator -- (int) { return I (p--); } +template I &I::operator += (const difference_type &x) { p += x; return *this; } +template I &I::operator -= (const difference_type &x) { p -= x; return *this; } +template I I::operator + (const difference_type &x) const { return I (p + x); } +template I I::operator - (const difference_type &x) const { return I (p - x); } +template bool operator == (I &x, I &y) { return x.p == y.p; } +template bool operator == (const I &x, const I &y) { return x.p == y.p; } +template bool operator != (I &x, I &y) { return !(x == y); } +template bool operator != (const I &x, const I &y) { return !(x == y); } +template bool operator < (I &x, I &y) { return x.p < y.p; } +template bool operator < (const I &x, const I &y) { return x.p < y.p; } +template bool operator <= (I &x, I &y) { return x.p <= y.p; } +template bool operator <= (const I &x, const I &y) { return x.p <= y.p; } +template bool operator > (I &x, I &y) { return x.p > y.p; } +template bool operator > (const I &x, const I &y) { return x.p > y.p; } +template bool operator >= (I &x, I &y) { return x.p >= y.p; } +template bool operator >= (const I &x, const I &y) { return x.p >= y.p; } +template typename I::difference_type operator - (I &x, I &y) { return x.p - y.p; } +template typename I::difference_type operator - (const I &x, const I &y) { return x.p - y.p; } +template I operator + (typename I::difference_type x, const I &y) { return I (x + y.p); } + +struct R { R () {}; ~R () {}; I r; }; +struct T { T () {}; virtual ~T () {}; I t; }; +struct A : public R, virtual public T { A () {} I a; void m1 (const I &, const I &); }; +template +struct U { U () {}; virtual ~U () {}; Q t; }; +template +struct B : public R, virtual public U { B () {} Q a; void m2 (const Q &, const Q &, const I &, const I &); }; + +int d[64]; + +void +A::m1 (const I &x, const I &y) +{ + int w = 0; + #pragma omp parallel for private (a) reduction(|:w) + for (a = x; A::a < y - 33; a += 2) + w |= (1 << *A::a); + if (w != 0x55555555) + __builtin_abort (); + #pragma omp parallel for lastprivate (t) + for (T::t = x; t < y - 32; t += 3) + d[*T::t + 2] |= 1; + if (*T::t != 33) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)) + __builtin_abort (); + w = 0; + #pragma omp parallel for reduction(|:w) + for (a = x; A::a < y - 33; a += 2) + w |= (1 << *A::a); + if (w != 0x55555555) + __builtin_abort (); + #pragma omp taskloop + for (R::r = x; r < y - 32; R::r += 2) + d[*r + 8] |= 2; + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0) + | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0))) + __builtin_abort (); + #pragma omp taskloop collapse(2) + for (T::t = x; t < y - 57; t += 2) + for (a = x; A::a < y - 56; a++) + d[((*t << 2) | *a) + 3] |= 4; + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0) + | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0) + | ((i >= 3 && i < 32 + 3) ? 4 : 0))) + __builtin_abort (); +} + +template +void +B::m2 (const Q &u, const Q &v, const I &x, const I &y) +{ + int w = 0; + #pragma omp parallel for private (a) reduction(|:w) + for (a = u; B::a < v - 33; a += 2) + w |= (1 << *B::a); + if (w != 0x55555555) + __builtin_abort (); + #pragma omp parallel for lastprivate (U::t) + for (U::t = u; U::t < v - 32; U::t += 3) + d[*U::t + 2] |= 1; + if (*U::t != 33) + __builtin_abort (); + for (int i = 0; i < 64; i++) + if (d[i] != ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)) + __builtin_abort (); + w = 0; + #pragma omp parallel for reduction(|:w) + for (a = u; B::a < v - 33; a += 2) + w |= (1 << *B::a); + if (w != 0x55555555) + __builtin_abort (); + #pragma omp taskloop + for (R::r = x; r < y - 32; R::r += 2) + d[*r + 8] |= 2; + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0) + | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0))) + __builtin_abort (); + #pragma omp taskloop collapse(2) + for (U::t = u; U::t < v - 57; U::t += 2) + for (a = u; B::a < v - 56; a++) + d[((*U::t << 2) | *a) + 3] |= 4; + for (int i = 0; i < 64; i++) + if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0) + | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0) + | ((i >= 3 && i < 32 + 3) ? 4 : 0))) + __builtin_abort (); +} + +int +main () +{ + A a; + int b[128]; + for (int i = 0; i < 128; i++) + b[i] = i - 32; + a.m1 (&b[32], &b[96]); + for (int i = 0; i < 64; i++) + d[i] = 0; + B > c; + c.m2 (&b[32], &b[96], &b[32], &b[96]); + for (int i = 0; i < 64; i++) + d[i] = 0; + B d; + d.m2 (&b[32], &b[96], &b[32], &b[96]); +} Jakub