re PR tree-optimization/68128 (A huge regression in Parboil v2.5 OpenMP CUTCP test (2.5 times lower performance))

PR tree-optimization/68128
	* tree.h (OMP_CLAUSE_SHARED_READONLY): Define.
	* gimplify.c: Include gimple-walk.h.
	(enum gimplify_omp_var_data): Add GOVD_WRITTEN.
	(omp_notice_variable): Set flags to n->value if n already
	exists in target region, but we need to jump to do_outer.
	(omp_shared_to_firstprivate_optimizable_decl_p,
	omp_mark_stores, omp_find_stores_op, omp_find_stores_stmt): New
	functions.
	(gimplify_adjust_omp_clauses_1): Set OMP_CLAUSE_SHARED_READONLY
	on OMP_CLAUSE_SHARED if it is a scalar non-addressable that is
	not modified in the body.  Call omp_mark_stores for outer
	contexts on OMP_CLAUSE_SHARED clauses if they could be written
	in the body or on OMP_CLAUSE_LASTPRIVATE.
	(gimplify_adjust_omp_clauses): Add body argument, call
	omp_find_stores_{stmt,op} on the body through walk_gimple_seq.
	Set OMP_CLAUSE_SHARED_READONLY
	on OMP_CLAUSE_SHARED if it is a scalar non-addressable that is
	not modified in the body.  Call omp_mark_stores for outer
	contexts on OMP_CLAUSE_SHARED clauses if they could be written
	in the body or on OMP_CLAUSE_LASTPRIVATE or on OMP_CLAUSE_LINEAR
	without OMP_CLAUSE_LINEAR_NO_COPYOUT or on OMP_CLAUSE_REDUCTION.
	(gimplify_oacc_cache, gimplify_omp_parallel, gimplify_omp_task,
	gimplify_omp_for, gimplify_omp_workshare, gimplify_omp_target_update,
	gimplify_expr): Adjust gimplify_adjust_omp_clauses callers.
	* tree-nested.c (convert_nonlocal_omp_clauses,
	convert_local_omp_clauses): Clear OMP_CLAUSE_SHARED_READONLY on
	non-local vars or local vars referenced from nested routines.
	* omp-low.c (scan_sharing_clauses): For OMP_CLAUSE_SHARED_READONLY
	attempt to optimize it into OMP_CLAUSE_FIRSTPRIVATE.  Even for
	TREE_READONLY, don't call use_pointer_for_field with non-NULL
	second argument until we are sure we are keeping OMP_CLAUSE_SHARED.

	* gcc.dg/gomp/pr68128-1.c: New test.
	* gcc.dg/gomp/pr68128-2.c: New test.

From-SVN: r230932
This commit is contained in:
Jakub Jelinek 2015-11-26 11:18:50 +01:00 committed by Jakub Jelinek
parent a37a22da2d
commit 1a80d6b87d
8 changed files with 467 additions and 13 deletions

View File

@ -1,3 +1,38 @@
2015-11-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/68128
* tree.h (OMP_CLAUSE_SHARED_READONLY): Define.
* gimplify.c: Include gimple-walk.h.
(enum gimplify_omp_var_data): Add GOVD_WRITTEN.
(omp_notice_variable): Set flags to n->value if n already
exists in target region, but we need to jump to do_outer.
(omp_shared_to_firstprivate_optimizable_decl_p,
omp_mark_stores, omp_find_stores_op, omp_find_stores_stmt): New
functions.
(gimplify_adjust_omp_clauses_1): Set OMP_CLAUSE_SHARED_READONLY
on OMP_CLAUSE_SHARED if it is a scalar non-addressable that is
not modified in the body. Call omp_mark_stores for outer
contexts on OMP_CLAUSE_SHARED clauses if they could be written
in the body or on OMP_CLAUSE_LASTPRIVATE.
(gimplify_adjust_omp_clauses): Add body argument, call
omp_find_stores_{stmt,op} on the body through walk_gimple_seq.
Set OMP_CLAUSE_SHARED_READONLY
on OMP_CLAUSE_SHARED if it is a scalar non-addressable that is
not modified in the body. Call omp_mark_stores for outer
contexts on OMP_CLAUSE_SHARED clauses if they could be written
in the body or on OMP_CLAUSE_LASTPRIVATE or on OMP_CLAUSE_LINEAR
without OMP_CLAUSE_LINEAR_NO_COPYOUT or on OMP_CLAUSE_REDUCTION.
(gimplify_oacc_cache, gimplify_omp_parallel, gimplify_omp_task,
gimplify_omp_for, gimplify_omp_workshare, gimplify_omp_target_update,
gimplify_expr): Adjust gimplify_adjust_omp_clauses callers.
* tree-nested.c (convert_nonlocal_omp_clauses,
convert_local_omp_clauses): Clear OMP_CLAUSE_SHARED_READONLY on
non-local vars or local vars referenced from nested routines.
* omp-low.c (scan_sharing_clauses): For OMP_CLAUSE_SHARED_READONLY
attempt to optimize it into OMP_CLAUSE_FIRSTPRIVATE. Even for
TREE_READONLY, don't call use_pointer_for_field with non-NULL
second argument until we are sure we are keeping OMP_CLAUSE_SHARED.
2015-11-26 Paolo Bonzini <bonzini@gnu.org>
* doc/implement-c.texi (Integers Implementation): Make GCC's promises

View File

@ -56,7 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "cilk.h"
#include "gomp-constants.h"
#include "tree-dump.h"
#include "gimple-walk.h"
#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
#include "builtins.h"
@ -87,6 +87,9 @@ enum gimplify_omp_var_data
/* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
GOVD_MAP_ALWAYS_TO = 65536,
/* Flag for shared vars that are or might be stored to in the region. */
GOVD_WRITTEN = 131072,
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
| GOVD_LOCAL)
@ -6153,7 +6156,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
/* If nothing changed, there's nothing left to do. */
if ((n->value & flags) == flags)
return ret;
n->value |= flags;
flags |= n->value;
n->value = flags;
}
goto do_outer;
}
@ -7384,6 +7388,123 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
delete struct_map_to_clause;
}
/* Return true if DECL is a candidate for shared to firstprivate
optimization. We only consider non-addressable scalars, not
too big, and not references. */
static bool
omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
{
if (TREE_ADDRESSABLE (decl))
return false;
tree type = TREE_TYPE (decl);
if (!is_gimple_reg_type (type)
|| TREE_CODE (type) == REFERENCE_TYPE
|| TREE_ADDRESSABLE (type))
return false;
/* Don't optimize too large decls, as each thread/task will have
its own. */
HOST_WIDE_INT len = int_size_in_bytes (type);
if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
return false;
if (lang_hooks.decls.omp_privatize_by_reference (decl))
return false;
return true;
}
/* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
GOVD_WRITTEN in outer contexts. */
static void
omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
{
for (; ctx; ctx = ctx->outer_context)
{
splay_tree_node n = splay_tree_lookup (ctx->variables,
(splay_tree_key) decl);
if (n == NULL)
continue;
else if (n->value & GOVD_SHARED)
{
n->value |= GOVD_WRITTEN;
return;
}
else if (n->value & GOVD_DATA_SHARE_CLASS)
return;
}
}
/* Helper callback for walk_gimple_seq to discover possible stores
to omp_shared_to_firstprivate_optimizable_decl_p decls and set
GOVD_WRITTEN if they are GOVD_SHARED in some outer context
for those. */
static tree
omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
{
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
*walk_subtrees = 0;
if (!wi->is_lhs)
return NULL_TREE;
tree op = *tp;
do
{
if (handled_component_p (op))
op = TREE_OPERAND (op, 0);
else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
&& TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
else
break;
}
while (1);
if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
return NULL_TREE;
omp_mark_stores (gimplify_omp_ctxp, op);
return NULL_TREE;
}
/* Helper callback for walk_gimple_seq to discover possible stores
to omp_shared_to_firstprivate_optimizable_decl_p decls and set
GOVD_WRITTEN if they are GOVD_SHARED in some outer context
for those. */
static tree
omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
bool *handled_ops_p,
struct walk_stmt_info *wi)
{
gimple *stmt = gsi_stmt (*gsi_p);
switch (gimple_code (stmt))
{
/* Don't recurse on OpenMP constructs for which
gimplify_adjust_omp_clauses already handled the bodies,
except handle gimple_omp_for_pre_body. */
case GIMPLE_OMP_FOR:
*handled_ops_p = true;
if (gimple_omp_for_pre_body (stmt))
walk_gimple_seq (gimple_omp_for_pre_body (stmt),
omp_find_stores_stmt, omp_find_stores_op, wi);
break;
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_CRITICAL:
*handled_ops_p = true;
break;
default:
break;
}
return NULL_TREE;
}
struct gimplify_adjust_omp_clauses_data
{
tree *list_p;
@ -7455,6 +7576,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
else
gcc_unreachable ();
if (((flags & GOVD_LASTPRIVATE)
|| (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
clause = build_omp_clause (input_location, code);
OMP_CLAUSE_DECL (clause) = decl;
OMP_CLAUSE_CHAIN (clause) = *list_p;
@ -7462,6 +7588,10 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
else if (code == OMP_CLAUSE_SHARED
&& (flags & GOVD_WRITTEN) == 0
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
OMP_CLAUSE_SHARED_READONLY (clause) = 1;
else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
{
tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
@ -7562,12 +7692,26 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
}
static void
gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p,
gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
enum tree_code code)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
tree c, decl;
if (body)
{
struct gimplify_omp_ctx *octx;
for (octx = ctx; octx; octx = octx->outer_context)
if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
break;
if (octx)
{
struct walk_stmt_info wi;
memset (&wi, 0, sizeof (wi));
walk_gimple_seq (body, omp_find_stores_stmt,
omp_find_stores_op, &wi);
}
}
while ((c = *list_p) != NULL)
{
splay_tree_node n;
@ -7594,6 +7738,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p,
OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
}
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
&& (n->value & GOVD_WRITTEN) == 0
&& DECL_P (decl)
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
OMP_CLAUSE_SHARED_READONLY (c) = 1;
else if (DECL_P (decl)
&& ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
&& (n->value & GOVD_WRITTEN) != 1)
|| (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
&& !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
}
break;
@ -7620,6 +7776,11 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p,
"%<lastprivate%> clauses on %<distribute%> "
"construct");
}
if (!remove
&& OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
&& DECL_P (decl)
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
break;
case OMP_CLAUSE_ALIGNED:
@ -7800,6 +7961,11 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, tree *list_p,
break;
case OMP_CLAUSE_REDUCTION:
decl = OMP_CLAUSE_DECL (c);
if (DECL_P (decl)
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
break;
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
case OMP_CLAUSE_IF:
@ -7876,7 +8042,8 @@ gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
OACC_CACHE);
gimplify_adjust_omp_clauses (pre_p, &OACC_CACHE_CLAUSES (expr), OACC_CACHE);
gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
OACC_CACHE);
/* TODO: Do something sensible with this information. */
@ -8023,7 +8190,7 @@ gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
else
pop_gimplify_context (NULL);
gimplify_adjust_omp_clauses (pre_p, &OMP_PARALLEL_CLAUSES (expr),
gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
OMP_PARALLEL);
g = gimple_build_omp_parallel (body,
@ -8060,7 +8227,8 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
else
pop_gimplify_context (NULL);
gimplify_adjust_omp_clauses (pre_p, &OMP_TASK_CLAUSES (expr), OMP_TASK);
gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
OMP_TASK);
g = gimple_build_omp_task (body,
OMP_TASK_CLAUSES (expr),
@ -8782,7 +8950,8 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
}
gimplify_adjust_omp_clauses (pre_p, &OMP_FOR_CLAUSES (orig_for_stmt),
gimplify_adjust_omp_clauses (pre_p, for_body,
&OMP_FOR_CLAUSES (orig_for_stmt),
TREE_CODE (orig_for_stmt));
int kind;
@ -9236,7 +9405,8 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
}
else
gimplify_and_add (OMP_BODY (expr), &body);
gimplify_adjust_omp_clauses (pre_p, &OMP_CLAUSES (expr), TREE_CODE (expr));
gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
TREE_CODE (expr));
switch (TREE_CODE (expr))
{
@ -9313,7 +9483,7 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
}
gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
ort, TREE_CODE (expr));
gimplify_adjust_omp_clauses (pre_p, &OMP_STANDALONE_CLAUSES (expr),
gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
TREE_CODE (expr));
stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr));
@ -10426,7 +10596,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_CRITICAL:
gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
pre_p, ORT_WORKSHARE, OMP_CRITICAL);
gimplify_adjust_omp_clauses (pre_p,
gimplify_adjust_omp_clauses (pre_p, body,
&OMP_CRITICAL_CLAUSES (*expr_p),
OMP_CRITICAL);
g = gimple_build_omp_critical (body,

View File

@ -1852,14 +1852,18 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
the receiver side will use them directly. */
if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
break;
by_ref = use_pointer_for_field (decl, ctx);
if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
break;
if (! TREE_READONLY (decl)
{
use_pointer_for_field (decl, ctx);
break;
}
by_ref = use_pointer_for_field (decl, NULL);
if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
|| TREE_ADDRESSABLE (decl)
|| by_ref
|| is_reference (decl))
{
by_ref = use_pointer_for_field (decl, ctx);
install_var_field (decl, by_ref, 3, ctx);
install_var_local (decl, ctx);
break;

View File

@ -1,3 +1,9 @@
2015-11-26 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/68128
* gcc.dg/gomp/pr68128-1.c: New test.
* gcc.dg/gomp/pr68128-2.c: New test.
2015-11-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR rtl-optimization/67226

View File

@ -0,0 +1,32 @@
/* PR tree-optimization/68128 */
/* { dg-do compile } */
/* { dg-options "-Ofast -fopenmp -fdump-tree-vect-details" } */
/* { dg-additional-options "-mavx" { target i?86-*-* x86_64-*-* } } */
/* Make sure the following loop is vectorized even when not using
firstprivate variables for scalar vars that are not modified
in the parallel region. */
void
foo (float *u, float v, float w, float x, float y, float z, float t)
{
int i, j, k, l;
float a, *b, c, s, e;
#pragma omp parallel for private (i, j, k, l, a, b, c, s, e)
for (j = 0; j < 1024; j++)
{
k = j * 64;
l = j * 64 + 63;
a = v + j * w;
b = u + j * 64;
for (i = k; i <= l; i++, b++, a += w)
{
c = a * a + y;
s = (1.f - c * x) * (1.f - c * x);
e = t * (1 / __builtin_sqrtf (c)) * s;
*b += (c < z ? e : 0);
}
}
}
/* { dg-final { scan-tree-dump "note: vectorized 1 loops in function" "vect" { target i?86-*-* x86_64-*-* } } } */

View File

@ -0,0 +1,198 @@
/* PR tree-optimization/68128 */
/* { dg-do compile } */
/* { dg-options "-O2 -fopenmp -fdump-tree-omplower" } */
extern int omp_get_thread_num (void);
extern int omp_get_ancestor_thread_num (int);
void b1 (int, int);
int
f1 (void)
{
int a1 = 1;
unsigned char a2 = 2;
unsigned long a3 = 3;
long long a4 = 4;
short a5 = 5;
char a6 = 6;
#pragma omp parallel shared (a1, a2, a3)
{
if (omp_get_thread_num () == 0)
{
a1 = a2;
a4 = a5;
}
b1 (a2, a6);
#pragma omp barrier
if (omp_get_thread_num () == 1)
{
a1 += a3;
a4 += a6;
}
}
return a1 + a2 + a3 + a4 + a5 + a6;
}
/* { dg-final { scan-tree-dump "shared\\(a1\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "firstprivate\\(a2\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "firstprivate\\(a3\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a4\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "firstprivate\\(a5\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "firstprivate\\(a6\\)" "omplower" } } */
struct S { int a, b; };
void b2 (int *, int *, int, int, struct S, struct S);
void
f2 (void)
{
struct S a7 = { 7, 7 }, a8 = { 8, 8 };
int a9 = 9, a10 = 10;
short a11[2] = { 11, 11 };
char a12[1] = { 12 };
#pragma omp parallel shared (a7, a9, a11)
{
b2 (&a9, &a10, a11[1], a12[0], a7, a8);
}
}
/* { dg-final { scan-tree-dump "shared\\(a7\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a8\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a9\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a10\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a11\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a12\\)" "omplower" } } */
void b3 (_Complex float, _Complex float);
_Complex float
f3 (void)
{
_Complex float a13 = 13.0f, a14 = 14.0f, a15 = 15.0f, a16 = 16.0f;
#pragma omp parallel shared (a13, a15)
{
#pragma omp parallel shared (a14)
{
if (omp_get_thread_num () == 0 && omp_get_ancestor_thread_num (1) == 1)
__imag__ a13 = __real__ a15;
else if (omp_get_thread_num () == 1 && omp_get_ancestor_thread_num (1) == 0)
__real__ a14 = __imag__ a16;
b3 (a15, a16);
}
}
return a13 + a14 + a15 + a16;
}
/* { dg-final { scan-tree-dump-times "shared\\(a13\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a14\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "firstprivate\\(a15\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "firstprivate\\(a16\\)" 2 "omplower" } } */
int
f4 (void)
{
int a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22, a23 = 23, a24 = 0, a25 = 0, a26 = 0;
int i;
#pragma omp task shared (a17)
b1 (a17, a18);
b1 (a17, a18);
#pragma omp taskwait
#pragma omp parallel shared (a19)
{
#pragma omp task shared (a19)
{
a19 = 1;
}
#pragma omp task shared (a20)
a20 = a21;
#pragma omp for firstprivate (a25) lastprivate (a22) linear (a23:2) reduction (+:a24) private (a26)
for (i = 0; i < 10; i++)
{
a26 = i;
a22 = a26 + 7;
a23 += 2;
a24 += i;
a25++;
}
}
return a22 + a23 + a24 + a25 + a26;
}
/* { dg-final { scan-tree-dump "firstprivate\\(a17\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "firstprivate\\(a18\\)" "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a19\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a20\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "firstprivate\\(a21\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "lastprivate\\(a22\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a22\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "linear\\(a23:2\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a23\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "reduction\\(.:a24\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "shared\\(a24\\)" 1 "omplower" } } */
/* { dg-final { scan-tree-dump-times "firstprivate\\(a25\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "private\\(a26\\)" 1 "omplower" } } */
void
f5 (void)
{
int a27 = 27, a28 = 28, a29 = 29, a30 = 30;
#pragma omp target data map (tofrom: a27, a28)
{
#pragma omp target map (tofrom: a27)
a27++;
#pragma omp parallel shared (a27, a28)
{
#pragma omp critical
{
/* This might modify a27 for non-shared memory offloading. */
#pragma omp target update to (a27)
#pragma omp target map (always, from: a28) private (a30)
{
a28++;
a29++;
a30 = a29;
}
}
#pragma omp barrier
b1 (a27, a28);
}
}
}
/* { dg-final { scan-tree-dump "shared\\(a27\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a28\\)" "omplower" } } */
/* { dg-final { scan-tree-dump-times "firstprivate\\(a29\\)" 2 "omplower" } } */
/* { dg-final { scan-tree-dump-times "private\\(a30\\)" 1 "omplower" } } */
int
f6 (void)
{
int a31 = 31, a32 = 32, a33 = 33, a34 = 34;
#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
{
a31 = 9;
}
#pragma omp section
{
int i = 10;
__builtin_memcpy (&a32, &i, sizeof (int));
}
}
#pragma omp single
a33 = 11;
#pragma omp atomic
a34++;
}
return a31 + a32 + a33 + a34;
}
/* { dg-final { scan-tree-dump "shared\\(a31\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a32\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a33\\)" "omplower" } } */
/* { dg-final { scan-tree-dump "shared\\(a34\\)" "omplower" } } */

View File

@ -1081,6 +1081,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
break;
if (decl_function_context (decl) != info->context)
{
if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
OMP_CLAUSE_SHARED_READONLY (clause) = 0;
bitmap_set_bit (new_suppress, DECL_UID (decl));
OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_PRIVATE)
@ -1732,6 +1734,8 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
tree field = lookup_field_for_decl (info, decl, NO_INSERT);
if (field)
{
if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_SHARED)
OMP_CLAUSE_SHARED_READONLY (clause) = 0;
bitmap_set_bit (new_suppress, DECL_UID (decl));
OMP_CLAUSE_DECL (clause)
= get_local_debug_decl (info, decl, field);

View File

@ -1453,6 +1453,11 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_CLAUSE_SHARED_FIRSTPRIVATE(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SHARED)->base.public_flag)
/* True on a SHARED clause if a scalar is not modified in the body and
thus could be optimized as firstprivate. */
#define OMP_CLAUSE_SHARED_READONLY(NODE) \
TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SHARED))
#define OMP_CLAUSE_IF_MODIFIER(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF)->omp_clause.subcode.if_modifier)