mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-14 05:20:25 +08:00
openmp: Implement allocate clause in omp lowering.
For now, task/taskloop constructs aren't handled and C/C++ array reductions and reductions with task or inscan modifiers need further work. Instead of calling omp_alloc/omp_free (where the former doesn't have alignment argument and omp_aligned_alloc is 5.1 only feature), this calls GOMP_alloc/GOMP_free, so that the library can fail if it would fall back into NULL (exception is zero length allocations). 2020-11-12 Jakub Jelinek <jakub@redhat.com> gcc/ * builtin-types.def (BT_FN_PTR_SIZE_SIZE_PTRMODE): New function type. * omp-builtins.def (BUILT_IN_GOACC_DECLARE): Move earlier. (BUILT_IN_GOMP_ALLOC, BUILT_IN_GOMP_FREE): New builtins. * gimplify.c (gimplify_scan_omp_clauses): Force allocator into a decl if it is not NULL, INTEGER_CST or decl. (gimplify_adjust_omp_clauses): Clear GOVD_EXPLICIT on explicit clauses which are being removed. Remove allocate clauses for variables not seen if they are private, firstprivate or linear too. Call omp_notice_variable on the allocator otherwise. (gimplify_omp_for): Handle iterator vars mentioned in allocate clauses similarly to non-is_gimple_reg iterators. * omp-low.c (struct omp_context): Add allocate_map field. (delete_omp_context): Delete it. (scan_sharing_clauses): Fill it from allocate clauses. Remove it if mentioned also in shared clause. (lower_private_allocate): New function. (lower_rec_input_clauses): Handle allocate clause for privatized variables, except for task/taskloop, C/C++ array reductions for now and task/inscan variables. (lower_send_shared_vars): Don't consider variables in allocate_map as shared. * omp-expand.c (expand_omp_for_generic, expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Use expand_omp_build_assign instead of gimple_build_assign + gsi_insert_after. * builtins.c (builtin_fnspec): Handle BUILTIN_GOMP_ALLOC and BUILTIN_GOMP_FREE. * tree-ssa-ccp.c (evaluate_stmt): Handle BUILTIN_GOMP_ALLOC. * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Handle BUILTIN_GOMP_ALLOC. (mark_all_reaching_defs_necessary_1): Handle BUILTIN_GOMP_ALLOC and BUILTIN_GOMP_FREE. (propagate_necessity): Likewise. gcc/fortran/ * f95-lang.c (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST): Define. (gfc_init_builtin_functions): Add alloc_size and warn_unused_result attributes to __builtin_GOMP_alloc. * types.def (BT_PTRMODE): New primitive type. (BT_FN_VOID_PTR_PTRMODE, BT_FN_PTR_SIZE_SIZE_PTRMODE): New function types. libgomp/ * libgomp.map (GOMP_alloc, GOMP_free): Export at GOMP_5.0.1. * omp.h.in (omp_alloc): Add malloc and alloc_size attributes. * libgomp_g.h (GOMP_alloc, GOMP_free): Declare. * allocator.c (omp_aligned_alloc): New for now static function, add alignment argument and handle it. (omp_alloc): Reimplement using omp_aligned_alloc. (GOMP_alloc, GOMP_free): New functions. (omp_free): Add ialias. * testsuite/libgomp.c-c++-common/allocate-1.c: New test. * testsuite/libgomp.c++/allocate-1.C: New test.
This commit is contained in:
parent
9106c51e57
commit
6fcc3cac42
@ -637,6 +637,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_SIZE_SIZE_PTR, BT_VOID, BT_SIZE, BT_SIZE,
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_SIZE_BOOL,
|
||||
BT_PTR, BT_PTR, BT_CONST_SIZE, BT_BOOL)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
|
||||
BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
|
||||
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
|
||||
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
|
||||
|
@ -13023,6 +13023,7 @@ builtin_fnspec (tree callee)
|
||||
case BUILT_IN_MALLOC:
|
||||
case BUILT_IN_ALIGNED_ALLOC:
|
||||
case BUILT_IN_CALLOC:
|
||||
case BUILT_IN_GOMP_ALLOC:
|
||||
return "mC";
|
||||
CASE_BUILT_IN_ALLOCA:
|
||||
return "mc";
|
||||
@ -13044,6 +13045,7 @@ builtin_fnspec (tree callee)
|
||||
across it. */
|
||||
case BUILT_IN_STACK_RESTORE:
|
||||
case BUILT_IN_FREE:
|
||||
case BUILT_IN_GOMP_FREE:
|
||||
return ".co ";
|
||||
case BUILT_IN_VA_END:
|
||||
return ".cO ";
|
||||
|
@ -531,7 +531,7 @@ gfc_builtin_function (tree decl)
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* So far we need just these 7 attribute types. */
|
||||
/* So far we need just these 8 attribute types. */
|
||||
#define ATTR_NULL 0
|
||||
#define ATTR_LEAF_LIST (ECF_LEAF)
|
||||
#define ATTR_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF)
|
||||
@ -540,6 +540,8 @@ gfc_builtin_function (tree decl)
|
||||
#define ATTR_PURE_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF | ECF_PURE)
|
||||
#define ATTR_NOTHROW_LIST (ECF_NOTHROW)
|
||||
#define ATTR_CONST_NOTHROW_LIST (ECF_NOTHROW | ECF_CONST)
|
||||
#define ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST \
|
||||
(ECF_NOTHROW)
|
||||
|
||||
static void
|
||||
gfc_define_builtin (const char *name, tree type, enum built_in_function code,
|
||||
@ -1236,6 +1238,13 @@ gfc_init_builtin_functions (void)
|
||||
#undef DEF_GOACC_BUILTIN
|
||||
#undef DEF_GOACC_BUILTIN_COMPILER
|
||||
#undef DEF_GOMP_BUILTIN
|
||||
tree gomp_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
|
||||
tree two = build_int_cst (integer_type_node, 2);
|
||||
DECL_ATTRIBUTES (gomp_alloc)
|
||||
= tree_cons (get_identifier ("warn_unused_result"), NULL_TREE,
|
||||
tree_cons (get_identifier ("alloc_size"),
|
||||
build_tree_list (NULL_TREE, two),
|
||||
DECL_ATTRIBUTES (gomp_alloc)));
|
||||
}
|
||||
|
||||
gfc_define_builtin ("__builtin_trap", builtin_types[BT_FN_VOID],
|
||||
|
@ -70,6 +70,7 @@ DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PTR,
|
||||
build_pointer_type
|
||||
(build_qualified_type (void_type_node,
|
||||
TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
|
||||
DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
|
||||
DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
|
||||
DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
|
||||
DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
|
||||
@ -117,6 +118,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
|
||||
BT_CONST_VOLATILE_PTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE,
|
||||
BT_VOID, BT_PTR, BT_PTRMODE)
|
||||
|
||||
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
|
||||
|
||||
@ -149,6 +152,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16,
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_SIZE_SIZE_PTR, BT_VOID, BT_SIZE, BT_SIZE,
|
||||
BT_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
|
||||
BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
|
||||
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
||||
|
@ -9904,10 +9904,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
|
||||
remove = true;
|
||||
break;
|
||||
}
|
||||
else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
|
||||
|| (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
|
||||
== INTEGER_CST))
|
||||
;
|
||||
else if (code == OMP_TASKLOOP
|
||||
&& OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
|
||||
&& (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
|
||||
!= INTEGER_CST))
|
||||
|| !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
|
||||
OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
|
||||
= get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
|
||||
pre_p, NULL, false);
|
||||
@ -10475,6 +10477,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
|
||||
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
|
||||
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
|
||||
}
|
||||
else
|
||||
n->value &= ~GOVD_EXPLICIT;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_LASTPRIVATE:
|
||||
@ -10774,6 +10778,41 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
|
||||
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
|
||||
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_ALLOCATE:
|
||||
decl = OMP_CLAUSE_DECL (c);
|
||||
n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
|
||||
if (n != NULL && !(n->value & GOVD_SEEN))
|
||||
{
|
||||
if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
|
||||
!= 0
|
||||
&& (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
|
||||
remove = true;
|
||||
}
|
||||
if (!remove
|
||||
&& OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
|
||||
&& TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
|
||||
&& ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
|
||||
|| (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
|
||||
|| (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
|
||||
{
|
||||
tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
|
||||
n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
|
||||
if (n == NULL)
|
||||
{
|
||||
enum omp_clause_default_kind default_kind
|
||||
= ctx->default_kind;
|
||||
ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
|
||||
omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
|
||||
true);
|
||||
ctx->default_kind = default_kind;
|
||||
}
|
||||
else
|
||||
omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
|
||||
true);
|
||||
}
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_COPYIN:
|
||||
case OMP_CLAUSE_COPYPRIVATE:
|
||||
case OMP_CLAUSE_IF:
|
||||
@ -10823,7 +10862,6 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
|
||||
case OMP_CLAUSE_FINALIZE:
|
||||
case OMP_CLAUSE_INCLUSIVE:
|
||||
case OMP_CLAUSE_EXCLUSIVE:
|
||||
case OMP_CLAUSE_ALLOCATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -11623,6 +11661,15 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
|
||||
c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
|
||||
if (c)
|
||||
tile = list_length (OMP_CLAUSE_TILE_LIST (c));
|
||||
c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
|
||||
hash_set<tree> *allocate_uids = NULL;
|
||||
if (c)
|
||||
{
|
||||
allocate_uids = new hash_set<tree>;
|
||||
for (; c; c = OMP_CLAUSE_CHAIN (c))
|
||||
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
|
||||
allocate_uids->add (OMP_CLAUSE_DECL (c));
|
||||
}
|
||||
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
|
||||
{
|
||||
t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
|
||||
@ -11949,12 +11996,13 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
|
||||
as an iteration counter. This is valid, since DECL cannot be
|
||||
modified in the body of the loop. Similarly for any iteration vars
|
||||
in simd with collapse > 1 where the iterator vars must be
|
||||
lastprivate. */
|
||||
lastprivate. And similarly for vars mentioned in allocate clauses. */
|
||||
if (orig_for_stmt != for_stmt)
|
||||
var = decl;
|
||||
else if (!is_gimple_reg (decl)
|
||||
|| (ort == ORT_SIMD
|
||||
&& TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1))
|
||||
&& TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
|
||||
|| (allocate_uids && allocate_uids->contains (decl)))
|
||||
{
|
||||
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
|
||||
/* Make sure omp_add_variable is not called on it prematurely.
|
||||
@ -12181,6 +12229,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
|
||||
}
|
||||
|
||||
BITMAP_FREE (has_decl_expr);
|
||||
delete allocate_uids;
|
||||
|
||||
if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
|
||||
|| (loop_p && orig_for_stmt == for_stmt))
|
||||
|
@ -47,6 +47,8 @@ DEF_GOACC_BUILTIN (BUILT_IN_GOACC_UPDATE, "GOACC_update",
|
||||
DEF_GOACC_BUILTIN (BUILT_IN_GOACC_WAIT, "GOACC_wait",
|
||||
BT_FN_VOID_INT_INT_VAR,
|
||||
ATTR_NOTHROW_LIST)
|
||||
DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
|
||||
BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
|
||||
|
||||
DEF_GOACC_BUILTIN_COMPILER (BUILT_IN_ACC_ON_DEVICE, "acc_on_device",
|
||||
BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
@ -444,5 +446,8 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK_REDUCTION_REMAP,
|
||||
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
|
||||
"GOMP_workshare_task_reduction_unregister",
|
||||
BT_FN_VOID_BOOL, ATTR_NOTHROW_LEAF_LIST)
|
||||
DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
|
||||
BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
|
||||
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
|
||||
"GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
|
||||
ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
|
||||
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
|
||||
"GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
|
||||
|
@ -4255,8 +4255,7 @@ expand_omp_for_generic (struct omp_region *region,
|
||||
: POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
|
||||
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
|
||||
false, GSI_CONTINUE_LINKING);
|
||||
assign_stmt = gimple_build_assign (dest, t);
|
||||
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
|
||||
expand_omp_build_assign (&gsi, dest, t, true);
|
||||
}
|
||||
if (fd->collapse > 1)
|
||||
expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
|
||||
@ -5250,8 +5249,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
|
||||
: POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
|
||||
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
|
||||
false, GSI_CONTINUE_LINKING);
|
||||
assign_stmt = gimple_build_assign (dest, t);
|
||||
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
|
||||
expand_omp_build_assign (&gsi, dest, t, true);
|
||||
}
|
||||
if (fd->collapse > 1)
|
||||
{
|
||||
@ -5974,8 +5972,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
|
||||
: POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
|
||||
t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
|
||||
false, GSI_CONTINUE_LINKING);
|
||||
assign_stmt = gimple_build_assign (dest, t);
|
||||
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
|
||||
expand_omp_build_assign (&gsi, dest, t, true);
|
||||
}
|
||||
if (fd->collapse > 1)
|
||||
expand_omp_for_init_vars (fd, &gsi, counts, NULL, inner_stmt, startvar);
|
||||
|
146
gcc/omp-low.c
146
gcc/omp-low.c
@ -126,6 +126,10 @@ struct omp_context
|
||||
corresponding tracking loop iteration variables. */
|
||||
hash_map<tree, tree> *lastprivate_conditional_map;
|
||||
|
||||
/* And a hash map from the allocate variables to their corresponding
|
||||
allocators. */
|
||||
hash_map<tree, tree> *allocate_map;
|
||||
|
||||
/* A tree_list of the reduction clauses in this context. This is
|
||||
only used for checking the consistency of OpenACC reduction
|
||||
clauses in scan_omp_for and is not guaranteed to contain a valid
|
||||
@ -1043,6 +1047,7 @@ delete_omp_context (splay_tree_value value)
|
||||
}
|
||||
|
||||
delete ctx->lastprivate_conditional_map;
|
||||
delete ctx->allocate_map;
|
||||
|
||||
XDELETE (ctx);
|
||||
}
|
||||
@ -1114,6 +1119,22 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
|
||||
tree c, decl;
|
||||
bool scan_array_reductions = false;
|
||||
|
||||
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
|
||||
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
|
||||
&& (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
|
||||
/* omp_default_mem_alloc is 1 */
|
||||
|| !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))))
|
||||
{
|
||||
if (is_task_ctx (ctx))
|
||||
continue; /* For now. */
|
||||
if (ctx->allocate_map == NULL)
|
||||
ctx->allocate_map = new hash_map<tree, tree>;
|
||||
ctx->allocate_map->put (OMP_CLAUSE_DECL (c),
|
||||
OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
|
||||
? OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
|
||||
: integer_zero_node);
|
||||
}
|
||||
|
||||
for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
|
||||
{
|
||||
bool by_ref;
|
||||
@ -1130,6 +1151,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
|
||||
|
||||
case OMP_CLAUSE_SHARED:
|
||||
decl = OMP_CLAUSE_DECL (c);
|
||||
if (ctx->allocate_map && ctx->allocate_map->get (decl))
|
||||
ctx->allocate_map->remove (decl);
|
||||
/* Ignore shared directives in teams construct inside of
|
||||
target construct. */
|
||||
if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
|
||||
@ -4358,6 +4381,68 @@ task_reduction_read (gimple_seq *ilist, tree tskred_temp, tree type,
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Lower early initialization of privatized variable NEW_VAR
|
||||
if it needs an allocator (has allocate clause). */
|
||||
|
||||
static bool
|
||||
lower_private_allocate (tree var, tree new_var, tree &allocator,
|
||||
tree &allocate_ptr, gimple_seq *ilist,
|
||||
omp_context *ctx, bool is_ref, tree size)
|
||||
{
|
||||
if (allocator)
|
||||
return false;
|
||||
gcc_assert (allocate_ptr == NULL_TREE);
|
||||
if (ctx->allocate_map && DECL_P (new_var))
|
||||
if (tree *allocatorp = ctx->allocate_map->get (var))
|
||||
allocator = *allocatorp;
|
||||
if (allocator == NULL_TREE)
|
||||
return false;
|
||||
if (!is_ref && omp_is_reference (var))
|
||||
return false;
|
||||
|
||||
if (TREE_CODE (allocator) != INTEGER_CST)
|
||||
allocator = build_outer_var_ref (allocator, ctx);
|
||||
allocator = fold_convert (pointer_sized_int_node, allocator);
|
||||
if (TREE_CODE (allocator) != INTEGER_CST)
|
||||
{
|
||||
tree var = create_tmp_var (TREE_TYPE (allocator));
|
||||
gimplify_assign (var, allocator, ilist);
|
||||
allocator = var;
|
||||
}
|
||||
|
||||
tree ptr_type, align, sz;
|
||||
if (is_ref)
|
||||
{
|
||||
ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
|
||||
align = build_int_cst (size_type_node,
|
||||
TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
|
||||
sz = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr_type = build_pointer_type (TREE_TYPE (new_var));
|
||||
align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (new_var));
|
||||
sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
|
||||
}
|
||||
if (TREE_CODE (sz) != INTEGER_CST)
|
||||
{
|
||||
tree szvar = create_tmp_var (size_type_node);
|
||||
gimplify_assign (szvar, sz, ilist);
|
||||
sz = szvar;
|
||||
}
|
||||
allocate_ptr = create_tmp_var (ptr_type);
|
||||
tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
|
||||
gimple *g = gimple_build_call (a, 3, align, sz, allocator);
|
||||
gimple_call_set_lhs (g, allocate_ptr);
|
||||
gimple_seq_add_stmt (ilist, g);
|
||||
if (!is_ref)
|
||||
{
|
||||
SET_DECL_VALUE_EXPR (new_var, build_simple_mem_ref (allocate_ptr));
|
||||
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
|
||||
from the receiver (aka child) side and initializers for REFERENCE_TYPE
|
||||
private variables. Initialization statements go in ILIST, while calls
|
||||
@ -4523,6 +4608,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
bool task_reduction_p = false;
|
||||
bool task_reduction_needs_orig_p = false;
|
||||
tree cond = NULL_TREE;
|
||||
tree allocator, allocate_ptr;
|
||||
|
||||
switch (c_kind)
|
||||
{
|
||||
@ -4659,6 +4745,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
if (task_reduction_p != (pass >= 2))
|
||||
continue;
|
||||
|
||||
allocator = NULL_TREE;
|
||||
allocate_ptr = NULL_TREE;
|
||||
new_var = var = OMP_CLAUSE_DECL (c);
|
||||
if ((c_kind == OMP_CLAUSE_REDUCTION
|
||||
|| c_kind == OMP_CLAUSE_IN_REDUCTION)
|
||||
@ -5195,8 +5283,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
|
||||
if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
|
||||
{
|
||||
gcall *stmt;
|
||||
tree tmp, atmp;
|
||||
tree tmp;
|
||||
|
||||
ptr = DECL_VALUE_EXPR (new_var);
|
||||
gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
|
||||
@ -5204,16 +5291,25 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
gcc_assert (DECL_P (ptr));
|
||||
x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
|
||||
|
||||
/* void *tmp = __builtin_alloca */
|
||||
atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
|
||||
stmt = gimple_build_call (atmp, 2, x,
|
||||
size_int (DECL_ALIGN (var)));
|
||||
cfun->calls_alloca = 1;
|
||||
tmp = create_tmp_var_raw (ptr_type_node);
|
||||
gimple_add_tmp_var (tmp);
|
||||
gimple_call_set_lhs (stmt, tmp);
|
||||
if (lower_private_allocate (var, new_var, allocator,
|
||||
allocate_ptr, ilist, ctx,
|
||||
false, x))
|
||||
tmp = allocate_ptr;
|
||||
else
|
||||
{
|
||||
/* void *tmp = __builtin_alloca */
|
||||
tree atmp
|
||||
= builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
|
||||
gcall *stmt
|
||||
= gimple_build_call (atmp, 2, x,
|
||||
size_int (DECL_ALIGN (var)));
|
||||
cfun->calls_alloca = 1;
|
||||
tmp = create_tmp_var_raw (ptr_type_node);
|
||||
gimple_add_tmp_var (tmp);
|
||||
gimple_call_set_lhs (stmt, tmp);
|
||||
|
||||
gimple_seq_add_stmt (ilist, stmt);
|
||||
gimple_seq_add_stmt (ilist, stmt);
|
||||
}
|
||||
|
||||
x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
|
||||
gimplify_assign (ptr, x, ilist);
|
||||
@ -5237,6 +5333,10 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
x = build_receiver_ref (var, false, ctx);
|
||||
x = build_fold_addr_expr_loc (clause_loc, x);
|
||||
}
|
||||
else if (lower_private_allocate (var, new_var, allocator,
|
||||
allocate_ptr,
|
||||
ilist, ctx, true, x))
|
||||
x = allocate_ptr;
|
||||
else if (TREE_CONSTANT (x))
|
||||
{
|
||||
/* For reduction in SIMD loop, defer adding the
|
||||
@ -5349,6 +5449,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
tree nx;
|
||||
bool copy_ctor;
|
||||
copy_ctor = false;
|
||||
lower_private_allocate (var, new_var, allocator, allocate_ptr,
|
||||
ilist, ctx, false, NULL_TREE);
|
||||
nx = unshare_expr (new_var);
|
||||
if (is_simd
|
||||
&& OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
|
||||
@ -5494,6 +5596,13 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
x = lang_hooks.decls.omp_clause_dtor (c, new_var);
|
||||
if (x)
|
||||
gimplify_and_add (x, dlist);
|
||||
if (allocator)
|
||||
{
|
||||
tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
|
||||
gimple *g
|
||||
= gimple_build_call (f, 2, allocate_ptr, allocator);
|
||||
gimple_seq_add_stmt (dlist, g);
|
||||
}
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_LINEAR:
|
||||
@ -5535,6 +5644,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
goto do_dtor;
|
||||
}
|
||||
do_firstprivate:
|
||||
lower_private_allocate (var, new_var, allocator, allocate_ptr,
|
||||
ilist, ctx, false, NULL_TREE);
|
||||
x = build_outer_var_ref (var, ctx);
|
||||
if (is_simd)
|
||||
{
|
||||
@ -5722,6 +5833,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_private_allocate (var, new_var, allocator,
|
||||
allocate_ptr, ilist, ctx, false,
|
||||
NULL_TREE);
|
||||
x = build_outer_var_ref (var, ctx);
|
||||
|
||||
if (omp_is_reference (var)
|
||||
@ -6118,6 +6232,9 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_private_allocate (var, new_var, allocator,
|
||||
allocate_ptr, ilist, ctx,
|
||||
false, NULL_TREE);
|
||||
if (omp_is_reference (var) && is_simd)
|
||||
handle_simd_reference (clause_loc, new_vard, ilist);
|
||||
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
|
||||
@ -6132,6 +6249,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
|
||||
ref = build_outer_var_ref (var, ctx);
|
||||
gimplify_assign (ref, x, dlist);
|
||||
}
|
||||
if (allocator)
|
||||
goto do_dtor;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -7488,7 +7607,10 @@ lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
|
||||
continue;
|
||||
|
||||
nvar = maybe_lookup_decl (ovar, ctx);
|
||||
if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
|
||||
if (!nvar
|
||||
|| !DECL_HAS_VALUE_EXPR_P (nvar)
|
||||
|| (ctx->allocate_map
|
||||
&& ctx->allocate_map->get (ovar)))
|
||||
continue;
|
||||
|
||||
/* If CTX is a nested parallel directive. Find the immediately
|
||||
|
@ -1972,6 +1972,7 @@ evaluate_stmt (gimple *stmt)
|
||||
break;
|
||||
|
||||
case BUILT_IN_ALIGNED_ALLOC:
|
||||
case BUILT_IN_GOMP_ALLOC:
|
||||
{
|
||||
tree align = get_constant_value (gimple_call_arg (stmt, 0));
|
||||
if (align
|
||||
|
@ -239,6 +239,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
|
||||
CASE_BUILT_IN_ALLOCA:
|
||||
case BUILT_IN_STRDUP:
|
||||
case BUILT_IN_STRNDUP:
|
||||
case BUILT_IN_GOMP_ALLOC:
|
||||
return;
|
||||
|
||||
default:;
|
||||
@ -605,6 +606,8 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
|
||||
case BUILT_IN_CALLOC:
|
||||
CASE_BUILT_IN_ALLOCA:
|
||||
case BUILT_IN_FREE:
|
||||
case BUILT_IN_GOMP_ALLOC:
|
||||
case BUILT_IN_GOMP_FREE:
|
||||
return false;
|
||||
|
||||
default:;
|
||||
@ -879,7 +882,8 @@ propagate_necessity (bool aggressive)
|
||||
&& gimple_call_from_new_or_delete (as_a <gcall *> (stmt))
|
||||
&& gimple_call_operator_delete_p (as_a <gcall *> (stmt)));
|
||||
if (is_delete_operator
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_FREE))
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_FREE)
|
||||
|| gimple_call_builtin_p (stmt, BUILT_IN_GOMP_FREE))
|
||||
{
|
||||
tree ptr = gimple_call_arg (stmt, 0);
|
||||
gcall *def_stmt;
|
||||
@ -892,27 +896,26 @@ propagate_necessity (bool aggressive)
|
||||
&& ((DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
|
||||
&& (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC
|
||||
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
|
||||
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
|
||||
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC
|
||||
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_GOMP_ALLOC))
|
||||
|| (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee)
|
||||
&& gimple_call_from_new_or_delete (def_stmt))))
|
||||
{
|
||||
if (is_delete_operator)
|
||||
{
|
||||
if (!valid_new_delete_pair_p (def_stmt, stmt))
|
||||
mark_operand_necessary (gimple_call_arg (stmt, 0));
|
||||
if (is_delete_operator
|
||||
&& !valid_new_delete_pair_p (def_stmt, stmt))
|
||||
mark_operand_necessary (gimple_call_arg (stmt, 0));
|
||||
|
||||
/* Delete operators can have alignment and (or) size
|
||||
as next arguments. When being a SSA_NAME, they
|
||||
must be marked as necessary. */
|
||||
if (gimple_call_num_args (stmt) >= 2)
|
||||
for (unsigned i = 1; i < gimple_call_num_args (stmt);
|
||||
i++)
|
||||
{
|
||||
tree arg = gimple_call_arg (stmt, i);
|
||||
if (TREE_CODE (arg) == SSA_NAME)
|
||||
mark_operand_necessary (arg);
|
||||
}
|
||||
}
|
||||
/* Delete operators can have alignment and (or) size
|
||||
as next arguments. When being a SSA_NAME, they
|
||||
must be marked as necessary. Similarly GOMP_free. */
|
||||
if (gimple_call_num_args (stmt) >= 2)
|
||||
for (unsigned i = 1; i < gimple_call_num_args (stmt);
|
||||
i++)
|
||||
{
|
||||
tree arg = gimple_call_arg (stmt, i);
|
||||
if (TREE_CODE (arg) == SSA_NAME)
|
||||
mark_operand_necessary (arg);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -205,11 +205,12 @@ omp_destroy_allocator (omp_allocator_handle_t allocator)
|
||||
ialias (omp_init_allocator)
|
||||
ialias (omp_destroy_allocator)
|
||||
|
||||
void *
|
||||
omp_alloc (size_t size, omp_allocator_handle_t allocator)
|
||||
static void *
|
||||
omp_aligned_alloc (size_t alignment, size_t size,
|
||||
omp_allocator_handle_t allocator)
|
||||
{
|
||||
struct omp_allocator_data *allocator_data;
|
||||
size_t alignment, new_size;
|
||||
size_t new_size;
|
||||
void *ptr, *ret;
|
||||
|
||||
if (__builtin_expect (size == 0, 0))
|
||||
@ -227,12 +228,14 @@ retry:
|
||||
if (allocator > omp_max_predefined_alloc)
|
||||
{
|
||||
allocator_data = (struct omp_allocator_data *) allocator;
|
||||
alignment = allocator_data->alignment;
|
||||
if (alignment < allocator_data->alignment)
|
||||
alignment = allocator_data->alignment;
|
||||
}
|
||||
else
|
||||
{
|
||||
allocator_data = NULL;
|
||||
alignment = sizeof (void *);
|
||||
if (alignment < sizeof (void *))
|
||||
alignment = sizeof (void *);
|
||||
}
|
||||
|
||||
new_size = sizeof (struct omp_mem_header);
|
||||
@ -339,6 +342,27 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
omp_alloc (size_t size, omp_allocator_handle_t allocator)
|
||||
{
|
||||
return omp_aligned_alloc (1, size, allocator);
|
||||
}
|
||||
|
||||
/* Like omp_aligned_alloc, but apply on top of that:
|
||||
"For allocations that arise from this ... the null_fb value of the
|
||||
fallback allocator trait behaves as if the abort_fb had been specified." */
|
||||
|
||||
void *
|
||||
GOMP_alloc (size_t alignment, size_t size, uintptr_t allocator)
|
||||
{
|
||||
void *ret = omp_aligned_alloc (alignment, size,
|
||||
(omp_allocator_handle_t) allocator);
|
||||
if (__builtin_expect (ret == NULL, 0) && size)
|
||||
gomp_fatal ("Out of memory allocating %lu bytes",
|
||||
(unsigned long) size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
omp_free (void *ptr, omp_allocator_handle_t allocator)
|
||||
{
|
||||
@ -366,3 +390,11 @@ omp_free (void *ptr, omp_allocator_handle_t allocator)
|
||||
}
|
||||
free (data->ptr);
|
||||
}
|
||||
|
||||
ialias (omp_free)
|
||||
|
||||
void
|
||||
GOMP_free (void *ptr, uintptr_t allocator)
|
||||
{
|
||||
return omp_free (ptr, (omp_allocator_handle_t) allocator);
|
||||
}
|
||||
|
@ -359,6 +359,12 @@ GOMP_5.0 {
|
||||
GOMP_workshare_task_reduction_unregister;
|
||||
} GOMP_4.5;
|
||||
|
||||
GOMP_5.0.1 {
|
||||
global:
|
||||
GOMP_alloc;
|
||||
GOMP_free;
|
||||
} GOMP_5.0;
|
||||
|
||||
OACC_2.0 {
|
||||
global:
|
||||
acc_get_num_devices;
|
||||
|
@ -357,6 +357,11 @@ extern void GOMP_teams (unsigned int, unsigned int);
|
||||
extern void GOMP_teams_reg (void (*) (void *), void *, unsigned, unsigned,
|
||||
unsigned);
|
||||
|
||||
/* allocator.c */
|
||||
|
||||
extern void *GOMP_alloc (size_t, size_t, uintptr_t);
|
||||
extern void GOMP_free (void *, uintptr_t);
|
||||
|
||||
/* oacc-async.c */
|
||||
|
||||
extern void GOACC_wait (int, int, ...);
|
||||
|
@ -281,7 +281,7 @@ extern void omp_set_default_allocator (omp_allocator_handle_t) __GOMP_NOTHROW;
|
||||
extern omp_allocator_handle_t omp_get_default_allocator (void) __GOMP_NOTHROW;
|
||||
extern void *omp_alloc (__SIZE_TYPE__,
|
||||
omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
|
||||
__GOMP_NOTHROW;
|
||||
__GOMP_NOTHROW __attribute__((__malloc__, __alloc_size__ (1)));
|
||||
extern void omp_free (void *,
|
||||
omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR)
|
||||
__GOMP_NOTHROW;
|
||||
|
194
libgomp/testsuite/libgomp.c++/allocate-1.C
Normal file
194
libgomp/testsuite/libgomp.c++/allocate-1.C
Normal file
@ -0,0 +1,194 @@
|
||||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void
|
||||
foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocator_handle_t h, int fl)
|
||||
{
|
||||
int i;
|
||||
typedef int T[x];
|
||||
T v, w;
|
||||
T &v2 = v;
|
||||
T &w2 = w;
|
||||
int xo = x;
|
||||
for (i = 0; i < x; i++)
|
||||
w[i] = i;
|
||||
#pragma omp parallel private (y, v2) firstprivate (x) allocate (x, y, v2)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
v2[0] = 7;
|
||||
v2[41] = 8;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
if (v2[0] != 7 || v2[41] != 8)
|
||||
abort ();
|
||||
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
|
||||
| (uintptr_t) &v2[0]) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp teams
|
||||
#pragma omp parallel private (y) firstprivate (x, w2) allocate (h: x, y, w2)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42 || w2[17] != 17 || w2[41] != 41)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
w2[19]++;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1 || w2[19] != 20)
|
||||
abort ();
|
||||
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
|
||||
| (uintptr_t) &w2[0]) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp parallel for private (y) firstprivate (x) allocate (h: x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if (x != 42)
|
||||
abort ();
|
||||
y = 1;
|
||||
l = i;
|
||||
n += y + 15;
|
||||
r += i;
|
||||
if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
|
||||
| (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for lastprivate (l2) allocate (h: l2, l3) lastprivate (conditional: l3)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
l2[0] = i;
|
||||
l2[1] = i + 1;
|
||||
l2[2] = i + 2;
|
||||
l2[3] = i + 3;
|
||||
if (i < 37)
|
||||
l3 = i;
|
||||
if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
|
||||
abort ();
|
||||
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
bar (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocator_handle_t h)
|
||||
{
|
||||
int i;
|
||||
typedef int T[x];
|
||||
T v, w;
|
||||
T &v2 = v;
|
||||
T &w2 = w;
|
||||
int xo = x;
|
||||
for (i = 0; i < x; i++)
|
||||
w[i] = i;
|
||||
#pragma omp parallel private (y, v2) firstprivate (x) allocate (x, y, v2)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
v2[0] = 7;
|
||||
v2[41] = 8;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
if (v2[0] != 7 || v2[41] != 8)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp teams
|
||||
#pragma omp parallel private (y) firstprivate (x, w2) allocate (h: x, y, w2)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42 || w2[17] != 17 || w2[41] != 41)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp parallel for private (y) firstprivate (x) allocate (h: x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if (x != 42)
|
||||
abort ();
|
||||
y = 1;
|
||||
l = i;
|
||||
n += y + 15;
|
||||
r += i;
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for lastprivate (l2) allocate (h: l2, l3) lastprivate (conditional: l3)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
l2[0] = i;
|
||||
l2[1] = i + 1;
|
||||
l2[2] = i + 2;
|
||||
l2[3] = i + 3;
|
||||
if (i < 37)
|
||||
l3 = i;
|
||||
}
|
||||
}
|
||||
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
|
||||
abort ();
|
||||
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_alloctrait_t traits[3]
|
||||
= { { omp_atk_alignment, 64 },
|
||||
{ omp_atk_fallback, omp_atv_null_fb } };
|
||||
omp_allocator_handle_t a
|
||||
= omp_init_allocator (omp_default_mem_space, 2, traits);
|
||||
if (a == omp_null_allocator)
|
||||
abort ();
|
||||
omp_set_default_allocator (omp_default_mem_alloc);
|
||||
int x = 42, y = 0, r = 0, l, l2[4], l3, n = 8;
|
||||
foo (x, y, r, l, l2, l3, n, omp_null_allocator, 0);
|
||||
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
|
||||
l2[2] = -1; l2[3] = -1; n = 8;
|
||||
foo (x, y, r, l, l2, l3, n, omp_default_mem_alloc, 0);
|
||||
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
|
||||
l2[2] = -1; l2[3] = -1; n = 8;
|
||||
foo (x, y, r, l, l2, l3, n, a, 1);
|
||||
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
|
||||
l2[2] = -1; l2[3] = -1; n = 8;
|
||||
omp_set_default_allocator (a);
|
||||
foo (x, y, r, l, l2, l3, n, omp_null_allocator, 3);
|
||||
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
|
||||
l2[2] = -1; l2[3] = -1; n = 8;
|
||||
foo (x, y, r, l, l2, l3, n, omp_default_mem_alloc, 2);
|
||||
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
|
||||
l2[2] = -1; l2[3] = -1; n = 8;
|
||||
bar (x, y, r, l, l2, l3, n, a);
|
||||
omp_destroy_allocator (a);
|
||||
return 0;
|
||||
}
|
254
libgomp/testsuite/libgomp.c-c++-common/allocate-1.c
Normal file
254
libgomp/testsuite/libgomp.c-c++-common/allocate-1.c
Normal file
@ -0,0 +1,254 @@
|
||||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void
|
||||
foo (int x, omp_allocator_handle_t h, int fl)
|
||||
{
|
||||
int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
|
||||
int i2, j2, n2 = 9, l4;
|
||||
int i3, j3, n3 = 10, l5;
|
||||
int i4, j4, n4 = 11, l6;
|
||||
int i5;
|
||||
int v[x], w[x];
|
||||
int xo = x;
|
||||
for (i = 0; i < x; i++)
|
||||
w[i] = i;
|
||||
#pragma omp parallel private (y, v) firstprivate (x) allocate (x, y, v)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
v[0] = 7;
|
||||
v[41] = 8;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
if (v[0] != 7 || v[41] != 8)
|
||||
abort ();
|
||||
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
|
||||
| (uintptr_t) &v[0]) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp teams
|
||||
#pragma omp parallel private (y) firstprivate (x, w) allocate (h: x, y, w)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42 || w[17] != 17 || w[41] != 41)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
w[19]++;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1 || w[19] != 20)
|
||||
abort ();
|
||||
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
|
||||
| (uintptr_t) &w[0]) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp parallel for private (y) firstprivate (x) allocate (h: x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if (x != 42)
|
||||
abort ();
|
||||
y = 1;
|
||||
l = i;
|
||||
n += y + 15;
|
||||
r += i;
|
||||
if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
|
||||
| (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for lastprivate (l2) private (i1) allocate (h: l2, l3, i1) lastprivate (conditional: l3)
|
||||
for (i1 = 0; i1 < 64; i1++)
|
||||
{
|
||||
l2[0] = i1;
|
||||
l2[1] = i1 + 1;
|
||||
l2[2] = i1 + 2;
|
||||
l2[3] = i1 + 3;
|
||||
if (i1 < 37)
|
||||
l3 = i1;
|
||||
if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3 | (uintptr_t) &i1) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (h: n2, l4, i2, j2)
|
||||
for (i2 = 3; i2 < 5; i2++)
|
||||
for (j2 = 17; j2 < 22; j2 += 2)
|
||||
{
|
||||
n2 += 17;
|
||||
l4 = i2 * 31 + j2;
|
||||
if ((fl & 1) && (((uintptr_t) &l4 | (uintptr_t) &n2
|
||||
| (uintptr_t) &i2 | (uintptr_t) &j2) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (n3, l5, i3, j3)
|
||||
for (i3 = 3; i3 < 5; i3++)
|
||||
for (j3 = 17; j3 < 23; j3 += 2)
|
||||
{
|
||||
n3 += 17;
|
||||
l5 = i3 * 31 + j3;
|
||||
if ((fl & 2) && (((uintptr_t) &l5 | (uintptr_t) &n3
|
||||
| (uintptr_t) &i3 | (uintptr_t) &j3) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (h: n4, l6, i4, j4)
|
||||
for (i4 = 3; i4 < 5; i4++)
|
||||
for (j4 = 17; j4 < 22; j4 += 2)
|
||||
{
|
||||
n4 += 17;
|
||||
l6 = i4 * 31 + j4;
|
||||
if ((fl & 1) && (((uintptr_t) &l6 | (uintptr_t) &n4
|
||||
| (uintptr_t) &i4 | (uintptr_t) &j4) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
#pragma omp for lastprivate (i5) allocate (i5)
|
||||
for (i5 = 1; i5 < 17; i5 += 3)
|
||||
{
|
||||
if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0)
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
|
||||
abort ();
|
||||
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
|
||||
abort ();
|
||||
if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i5 != 19)
|
||||
abort ();
|
||||
}
|
||||
|
||||
void
|
||||
bar (int x, omp_allocator_handle_t h)
|
||||
{
|
||||
int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
|
||||
int i2, j2, n2 = 9, l4;
|
||||
int i3, j3, n3 = 10, l5;
|
||||
int i4, j4, n4 = 11, l6;
|
||||
int i5;
|
||||
int xo = x;
|
||||
#pragma omp parallel private (y) firstprivate (x) allocate (x, y)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp teams
|
||||
#pragma omp parallel private (y) firstprivate (x) allocate (h: x, y)
|
||||
{
|
||||
int *volatile p1 = &x;
|
||||
int *volatile p2 = &y;
|
||||
if (x != 42)
|
||||
abort ();
|
||||
#pragma omp barrier
|
||||
*p2 = 1;
|
||||
p1[0]++;
|
||||
#pragma omp barrier
|
||||
if (x != 43 || y != 1)
|
||||
abort ();
|
||||
}
|
||||
x = xo;
|
||||
#pragma omp parallel for private (y) firstprivate (x) allocate (h: x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
if (x != 42)
|
||||
abort ();
|
||||
y = 1;
|
||||
l = i;
|
||||
n += y + 15;
|
||||
r += i;
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp for lastprivate (l2) private (i1) allocate (h: l2, l3, i1) lastprivate (conditional: l3)
|
||||
for (i1 = 0; i1 < 64; i1++)
|
||||
{
|
||||
l2[0] = i1;
|
||||
l2[1] = i1 + 1;
|
||||
l2[2] = i1 + 2;
|
||||
l2[3] = i1 + 3;
|
||||
if (i1 < 37)
|
||||
l3 = i1;
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (h: n2, l4, i2, j2)
|
||||
for (i2 = 3; i2 < 5; i2++)
|
||||
for (j2 = 17; j2 < 22; j2 += 2)
|
||||
{
|
||||
n2 += 17;
|
||||
l4 = i2 * 31 + j2;
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (n3, l5, i3, j3)
|
||||
for (i3 = 3; i3 < 5; i3++)
|
||||
for (j3 = 17; j3 < 23; j3 += 2)
|
||||
{
|
||||
n3 += 17;
|
||||
l5 = i3 * 31 + j3;
|
||||
}
|
||||
#pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (h: n4, l6, i4, j4)
|
||||
for (i4 = 3; i4 < 5; i4++)
|
||||
for (j4 = 17; j4 < 22; j4 += 2)
|
||||
{
|
||||
n4 += 17;
|
||||
l6 = i4 * 31 + j4;
|
||||
}
|
||||
#pragma omp for lastprivate (i5) allocate (i5)
|
||||
for (i5 = 1; i5 < 17; i5 += 3)
|
||||
;
|
||||
}
|
||||
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
|
||||
abort ();
|
||||
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
|
||||
abort ();
|
||||
if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
|
||||
abort ();
|
||||
if (i5 != 19)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
omp_alloctrait_t traits[3]
|
||||
= { { omp_atk_alignment, 64 },
|
||||
{ omp_atk_fallback, omp_atv_null_fb } };
|
||||
omp_allocator_handle_t a
|
||||
= omp_init_allocator (omp_default_mem_space, 2, traits);
|
||||
if (a == omp_null_allocator)
|
||||
abort ();
|
||||
omp_set_default_allocator (omp_default_mem_alloc);
|
||||
foo (42, omp_null_allocator, 0);
|
||||
foo (42, omp_default_mem_alloc, 0);
|
||||
foo (42, a, 1);
|
||||
omp_set_default_allocator (a);
|
||||
foo (42, omp_null_allocator, 3);
|
||||
foo (42, omp_default_mem_alloc, 2);
|
||||
bar (42, a);
|
||||
omp_destroy_allocator (a);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user