diff options
Diffstat (limited to 'gcc/fortran/trans-openmp.c')
-rw-r--r-- | gcc/fortran/trans-openmp.c | 396 |
1 files changed, 379 insertions, 17 deletions
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index e77c191..fe47a96 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "trans-const.h" #include "arith.h" #include "omp-low.h" +#include "gomp-constants.h" int ompws_flags; @@ -1045,7 +1046,7 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p) return; tree orig_decl = decl; c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (c4) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (c4) = decl; OMP_CLAUSE_SIZE (c4) = size_int (0); decl = build_fold_indirect_ref (decl); @@ -1056,7 +1057,7 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p) || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl))) { c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (c3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (c3) = unshare_expr (decl); OMP_CLAUSE_SIZE (c3) = size_int (0); decl = build_fold_indirect_ref (decl); @@ -1073,11 +1074,11 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p) ptr = build_fold_indirect_ref (ptr); OMP_CLAUSE_DECL (c) = ptr; c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (c2) = OMP_CLAUSE_MAP_TO_PSET; + OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET); OMP_CLAUSE_DECL (c2) = decl; OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type); c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (c3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl); OMP_CLAUSE_SIZE (c3) = size_int (0); tree size = create_tmp_var (gfc_array_index_type); @@ -1718,6 +1719,21 @@ gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list, return list; } +static inline tree +gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr) +{ + gfc_se se; + tree result; + + gfc_init_se (&se, NULL ); + gfc_conv_expr (&se, expr); + gfc_add_block_to_block (block, &se.pre); + result = gfc_evaluate_now (se.expr, block); + gfc_add_block_to_block (block, &se.post); + + return result; +} + static tree gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, locus where, bool declare_simd = false) @@ -1761,7 +1777,17 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, goto add_clause; case OMP_LIST_UNIFORM: clause_code = OMP_CLAUSE_UNIFORM; - /* FALLTHROUGH */ + goto add_clause; + case OMP_LIST_USE_DEVICE: + clause_code = OMP_CLAUSE_USE_DEVICE; + goto add_clause; + case OMP_LIST_DEVICE_RESIDENT: + clause_code = OMP_CLAUSE_DEVICE_RESIDENT; + goto add_clause; + case OMP_LIST_CACHE: + clause_code = OMP_CLAUSE__CACHE_; + goto add_clause; + add_clause: omp_clauses = gfc_trans_omp_variable_list (clause_code, n, omp_clauses, @@ -1928,7 +1954,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, tree orig_decl = decl; node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node4) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node4) = decl; OMP_CLAUSE_SIZE (node4) = size_int (0); decl = build_fold_indirect_ref (decl); @@ -1938,7 +1964,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, { node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node3) = decl; OMP_CLAUSE_SIZE (node3) = size_int (0); decl = build_fold_indirect_ref (decl); @@ -1954,12 +1980,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, OMP_CLAUSE_DECL (node) = ptr; node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node2) = OMP_CLAUSE_MAP_TO_PSET; + OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET); OMP_CLAUSE_DECL (node2) = decl; OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type); node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl); OMP_CLAUSE_SIZE (node3) = size_int (0); @@ -2045,7 +2071,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, { node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node4) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node4) = decl; OMP_CLAUSE_SIZE (node4) = size_int (0); decl = build_fold_indirect_ref (decl); @@ -2057,12 +2083,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, ptr2 = gfc_conv_descriptor_data_get (decl); node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node2) = OMP_CLAUSE_MAP_TO_PSET; + OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET); OMP_CLAUSE_DECL (node2) = decl; OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type); node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl); } @@ -2077,7 +2103,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, } node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP); - OMP_CLAUSE_MAP_KIND (node3) = OMP_CLAUSE_MAP_POINTER; + OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER); OMP_CLAUSE_DECL (node3) = decl; } ptr2 = fold_convert (sizetype, ptr2); @@ -2087,16 +2113,37 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, switch (n->u.map_op) { case OMP_MAP_ALLOC: - OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_ALLOC; + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC); break; case OMP_MAP_TO: - OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_TO; + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO); break; case OMP_MAP_FROM: - OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_FROM; + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM); break; case OMP_MAP_TOFROM: - OMP_CLAUSE_MAP_KIND (node) = OMP_CLAUSE_MAP_TOFROM; + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM); + break; + case OMP_MAP_FORCE_ALLOC: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC); + break; + case OMP_MAP_FORCE_DEALLOC: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEALLOC); + break; + case OMP_MAP_FORCE_TO: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO); + break; + case OMP_MAP_FORCE_FROM: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM); + break; + case OMP_MAP_FORCE_TOFROM: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM); + break; + case OMP_MAP_FORCE_PRESENT: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT); + break; + case OMP_MAP_FORCE_DEVICEPTR: + OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR); break; default: gcc_unreachable (); @@ -2463,6 +2510,111 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, omp_clauses = gfc_trans_add_clause (c, omp_clauses); } + if (clauses->async) + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_ASYNC); + if (clauses->async_expr) + OMP_CLAUSE_ASYNC_EXPR (c) + = gfc_convert_expr_to_tree (block, clauses->async_expr); + else + OMP_CLAUSE_ASYNC_EXPR (c) = NULL; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->seq) + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->independent) + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_INDEPENDENT); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->wait_list) + { + gfc_expr_list *el; + + for (el = clauses->wait_list; el; el = el->next) + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_WAIT); + OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr); + OMP_CLAUSE_CHAIN (c) = omp_clauses; + omp_clauses = c; + } + } + if (clauses->num_gangs_expr) + { + tree num_gangs_var + = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_GANGS); + OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->num_workers_expr) + { + tree num_workers_var + = gfc_convert_expr_to_tree (block, clauses->num_workers_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_WORKERS); + OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->vector_length_expr) + { + tree vector_length_var + = gfc_convert_expr_to_tree (block, clauses->vector_length_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR_LENGTH); + OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->vector) + { + if (clauses->vector_expr) + { + tree vector_var + = gfc_convert_expr_to_tree (block, clauses->vector_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR); + OMP_CLAUSE_VECTOR_EXPR (c) = vector_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + else + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + } + if (clauses->worker) + { + if (clauses->worker_expr) + { + tree worker_var + = gfc_convert_expr_to_tree (block, clauses->worker_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER); + OMP_CLAUSE_WORKER_EXPR (c) = worker_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + else + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + } + if (clauses->gang) + { + if (clauses->gang_expr) + { + tree gang_var + = gfc_convert_expr_to_tree (block, clauses->gang_expr); + c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG); + OMP_CLAUSE_GANG_EXPR (c) = gang_var; + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + else + { + c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + } + return nreverse (omp_clauses); } @@ -2490,6 +2642,115 @@ gfc_trans_omp_code (gfc_code *code, bool force_empty) return stmt; } +/* Trans OpenACC directives. */ +/* parallel, kernels, data and host_data. */ +static tree +gfc_trans_oacc_construct (gfc_code *code) +{ + stmtblock_t block; + tree stmt, oacc_clauses; + enum tree_code construct_code; + + switch (code->op) + { + case EXEC_OACC_PARALLEL: + construct_code = OACC_PARALLEL; + break; + case EXEC_OACC_KERNELS: + construct_code = OACC_KERNELS; + break; + case EXEC_OACC_DATA: + construct_code = OACC_DATA; + break; + case EXEC_OACC_HOST_DATA: + construct_code = OACC_HOST_DATA; + break; + default: + gcc_unreachable (); + } + + gfc_start_block (&block); + oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, + code->loc); + stmt = gfc_trans_omp_code (code->block->next, true); + stmt = build2_loc (input_location, construct_code, void_type_node, stmt, + oacc_clauses); + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); +} + +/* update, enter_data, exit_data, cache. */ +static tree +gfc_trans_oacc_executable_directive (gfc_code *code) +{ + stmtblock_t block; + tree stmt, oacc_clauses; + enum tree_code construct_code; + + switch (code->op) + { + case EXEC_OACC_UPDATE: + construct_code = OACC_UPDATE; + break; + case EXEC_OACC_ENTER_DATA: + construct_code = OACC_ENTER_DATA; + break; + case EXEC_OACC_EXIT_DATA: + construct_code = OACC_EXIT_DATA; + break; + case EXEC_OACC_CACHE: + construct_code = OACC_CACHE; + break; + default: + gcc_unreachable (); + } + + gfc_start_block (&block); + oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, + code->loc); + stmt = build1_loc (input_location, construct_code, void_type_node, + oacc_clauses); + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); +} + +static tree +gfc_trans_oacc_wait_directive (gfc_code *code) +{ + stmtblock_t block; + tree stmt, t; + vec<tree, va_gc> *args; + int nparms = 0; + gfc_expr_list *el; + gfc_omp_clauses *clauses = code->ext.omp_clauses; + location_t loc = input_location; + + for (el = clauses->wait_list; el; el = el->next) + nparms++; + + vec_alloc (args, nparms + 2); + stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT); + + gfc_start_block (&block); + + if (clauses->async_expr) + t = gfc_convert_expr_to_tree (&block, clauses->async_expr); + else + t = build_int_cst (integer_type_node, -2); + + args->quick_push (t); + args->quick_push (build_int_cst (integer_type_node, nparms)); + + for (el = clauses->wait_list; el; el = el->next) + args->quick_push (gfc_convert_expr_to_tree (&block, el->expr)); + + stmt = build_call_expr_loc_vec (loc, stmt, args); + gfc_add_expr_to_block (&block, stmt); + + vec_free (args); + + return gfc_finish_block (&block); +} static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *); static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *); @@ -3115,6 +3376,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break; case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break; case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break; + case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break; default: gcc_unreachable (); } @@ -3129,6 +3391,68 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, return gfc_finish_block (&block); } +/* parallel loop and kernels loop. */ +static tree +gfc_trans_oacc_combined_directive (gfc_code *code) +{ + stmtblock_t block, *pblock = NULL; + gfc_omp_clauses construct_clauses, loop_clauses; + tree stmt, oacc_clauses = NULL_TREE; + enum tree_code construct_code; + + switch (code->op) + { + case EXEC_OACC_PARALLEL_LOOP: + construct_code = OACC_PARALLEL; + break; + case EXEC_OACC_KERNELS_LOOP: + construct_code = OACC_KERNELS; + break; + default: + gcc_unreachable (); + } + + gfc_start_block (&block); + + memset (&loop_clauses, 0, sizeof (loop_clauses)); + if (code->ext.omp_clauses != NULL) + { + memcpy (&construct_clauses, code->ext.omp_clauses, + sizeof (construct_clauses)); + loop_clauses.collapse = construct_clauses.collapse; + loop_clauses.gang = construct_clauses.gang; + loop_clauses.vector = construct_clauses.vector; + loop_clauses.worker = construct_clauses.worker; + loop_clauses.seq = construct_clauses.seq; + loop_clauses.independent = construct_clauses.independent; + construct_clauses.collapse = 0; + construct_clauses.gang = false; + construct_clauses.vector = false; + construct_clauses.worker = false; + construct_clauses.seq = false; + construct_clauses.independent = false; + oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses, + code->loc); + } + if (!loop_clauses.seq) + pblock = █ + else + pushlevel (); + stmt = gfc_trans_omp_do (code, code->op, pblock, &loop_clauses, NULL); + if (TREE_CODE (stmt) != BIND_EXPR) + stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); + else + poplevel (0, 0); + stmt = build2_loc (input_location, construct_code, void_type_node, stmt, + oacc_clauses); + if (code->op == EXEC_OACC_KERNELS_LOOP) + OACC_KERNELS_COMBINED (stmt) = 1; + else + OACC_PARALLEL_COMBINED (stmt) = 1; + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); +} + static tree gfc_trans_omp_flush (void) { @@ -4019,6 +4343,44 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) } tree +gfc_trans_oacc_declare (stmtblock_t *block, gfc_namespace *ns) +{ + tree oacc_clauses; + oacc_clauses = gfc_trans_omp_clauses (block, ns->oacc_declare_clauses, + ns->oacc_declare_clauses->loc); + return build1_loc (ns->oacc_declare_clauses->loc.lb->location, + OACC_DECLARE, void_type_node, oacc_clauses); +} + +tree +gfc_trans_oacc_directive (gfc_code *code) +{ + switch (code->op) + { + case EXEC_OACC_PARALLEL_LOOP: + case EXEC_OACC_KERNELS_LOOP: + return gfc_trans_oacc_combined_directive (code); + case EXEC_OACC_PARALLEL: + case EXEC_OACC_KERNELS: + case EXEC_OACC_DATA: + case EXEC_OACC_HOST_DATA: + return gfc_trans_oacc_construct (code); + case EXEC_OACC_LOOP: + return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses, + NULL); + case EXEC_OACC_UPDATE: + case EXEC_OACC_CACHE: + case EXEC_OACC_ENTER_DATA: + case EXEC_OACC_EXIT_DATA: + return gfc_trans_oacc_executable_directive (code); + case EXEC_OACC_WAIT: + return gfc_trans_oacc_wait_directive (code); + default: + gcc_unreachable (); + } +} + +tree gfc_trans_omp_directive (gfc_code *code) { switch (code->op) |