[gomp4.1] Add support for non-static data member iterators
Jakub Jelinek
jakub@redhat.com
Fri Jun 26 13:38:00 GMT 2015
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 <jakub@redhat.com>
* 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<tree> &);
extern void restore_omp_privatization_clauses (vec<tree> &);
@@ -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<tree> 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<tree, tree> *omp_private_member_map;
static vec<tree> 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<tree> &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<tree> &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 <tree, tree>;
while (!save.is_empty ())
{
@@ -6603,6 +6624,12 @@ restore_omp_privatization_clauses (vec<t
tree n = t;
if (t != error_mark_node)
{
+ if (t == integer_one_node)
+ {
+ omp_private_member_ignore_next = true;
+ gcc_assert (save.is_empty ());
+ break;
+ }
if (t == integer_zero_node)
t = save.pop ();
tree &v = omp_private_member_map->get_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 <omp.h>
--- 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 <omp.h>
--- 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 <typename Q>
+struct T { T () : t(d) {}; virtual ~T () {}; Q t; };
+template <typename Q>
+struct A : public R, virtual public T<Q> { A () : b(c), a(e) {} Q a; int &b; void m1 (); };
+int f[64];
+
+template <typename Q>
+void
+A<Q>::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<Q>::t)
+ for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t += 3)
+ f[T<Q>::t + 2] |= 2;
+ if (T<Q>::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<Q>::t)
+ for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t++)
+ f[T<Q>::t + 9] |= 4;
+ if (T<Q>::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<Q>::t = 0; T<Q>::t < 7; T<Q>::t += 2)
+ for (a = 0; A::a < 8; a++)
+ f[((T<Q>::t << 2) | a) + 3] |= 16;
+ if (T<Q>::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<Q>::t = 32;
+ a = 16;
+ #pragma omp parallel
+ #pragma omp single
+ #pragma omp taskloop simd collapse(2)
+ for (T<Q>::t = 0; T<Q>::t < 7; T<Q>::t += 2)
+ for (A::a = 0; a < 8; A::a++)
+ f[((T<Q>::t << 2) | A::a) + 3] |= 32;
+ if (T<Q>::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<int> 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 <typename T>
+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 <typename S> friend bool operator == (I<S> &, I<S> &);
+ template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator < (I<S> &, I<S> &);
+ template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator <= (I<S> &, I<S> &);
+ template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator > (I<S> &, I<S> &);
+ template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+ template <typename S> friend bool operator >= (I<S> &, I<S> &);
+ template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+ template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+ template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+ T *p;
+};
+template <typename T> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+struct R { R () {}; ~R () {}; I<int> r; };
+struct T { T () {}; virtual ~T () {}; I<int> t; };
+struct A : public R, virtual public T { A () {} I<int> a; void m1 (const I<int> &, const I<int> &); };
+template <typename Q>
+struct U { U () {}; virtual ~U () {}; Q t; };
+template <typename Q>
+struct B : public R, virtual public U<Q> { B () {} Q a; void m2 (const Q &, const Q &, const I<int> &, const I<int> &); };
+
+int d[64];
+
+void
+A::m1 (const I<int> &x, const I<int> &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 <typename Q>
+void
+B<Q>::m2 (const Q &u, const Q &v, const I<int> &x, const I<int> &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<Q>::t)
+ for (U<Q>::t = u; U<Q>::t < v - 32; U<Q>::t += 3)
+ d[*U<Q>::t + 2] |= 1;
+ if (*U<Q>::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<Q>::t = u; U<Q>::t < v - 57; U<Q>::t += 2)
+ for (a = u; B::a < v - 56; a++)
+ d[((*U<Q>::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<I<int> > c;
+ c.m2 (&b[32], &b[96], &b[32], &b[96]);
+ for (int i = 0; i < 64; i++)
+ d[i] = 0;
+ B<int *> d;
+ d.m2 (&b[32], &b[96], &b[32], &b[96]);
+}
Jakub
More information about the Gcc-patches
mailing list