diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d5f103ac1b..0a7a4174a67 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2016-01-26 Nathan Sidwell + + * omp-low.h (oacc_fn_attrib_kernels_p): Declare. + (set_oacc_fn_attrib): Add IS_KERNEL arg. + * omp-low.c (set_oacc_fn_attrib): Add IS_KERNEL arg. + (oacc_fn_attrib_kernels_p, oacc_fn_attrib_level): New. + (expand_omp_target): Pass is_kernel to set_oacc_fn_attrib. + (oacc_validate_dims): Add LEVEL arg, don't return level. + (new_oacc_loop_routine): Use oacc_fn_attrib_level, not + oacc_validate_dims. + (execute_oacc_device_lower): Adjust, add more dump output. + * tree-ssa-loop.c (gate_oacc_kernels): Use + oacc_fn_attrib_kernels_p. + * tree-parloops.c (create_parallel_loop): Adjust + set_oacc_fn_attrib call. + 2016-01-26 Jakub Jelinek PR lto/69254 diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 3615cbc5f9e..677ad64e7e3 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -12487,10 +12487,11 @@ replace_oacc_fn_attrib (tree fn, tree dims) /* Scan CLAUSES for launch dimensions and attach them to the oacc function attribute. Push any that are non-constant onto the ARGS - list, along with an appropriate GOMP_LAUNCH_DIM tag. */ + list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is + true, if these are for a kernels region offload function. */ void -set_oacc_fn_attrib (tree fn, tree clauses, vec *args) +set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec *args) { /* Must match GOMP_DIM ordering. */ static const omp_clause_code ids[] @@ -12515,6 +12516,9 @@ set_oacc_fn_attrib (tree fn, tree clauses, vec *args) non_const |= GOMP_DIM_MASK (ix); } attr = tree_cons (NULL_TREE, dim, attr); + /* Note kernelness with TREE_PUBLIC. */ + if (is_kernel) + TREE_PUBLIC (attr) = 1; } replace_oacc_fn_attrib (fn, attr); @@ -12583,6 +12587,36 @@ get_oacc_fn_attrib (tree fn) return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn)); } +/* Return true if this oacc fn attrib is for a kernels offload + region. We use the TREE_PUBLIC flag of each dimension -- only + need to check the first one. */ + +bool +oacc_fn_attrib_kernels_p (tree attr) +{ + return TREE_PUBLIC (TREE_VALUE (attr)); +} + +/* Return level at which oacc routine may spawn a partitioned loop, or + -1 if it is not a routine (i.e. is an offload fn). */ + +static int +oacc_fn_attrib_level (tree attr) +{ + tree pos = TREE_VALUE (attr); + + if (!TREE_PURPOSE (pos)) + return -1; + + int ix = 0; + for (ix = 0; ix != GOMP_DIM_MAX; + ix++, pos = TREE_CHAIN (pos)) + if (!integer_zerop (TREE_PURPOSE (pos))) + break; + + return ix; +} + /* Extract an oacc execution dimension from FN. FN must be an offloaded function or routine that has already had its execution dimensions lowered to the target-specific values. */ @@ -13125,6 +13159,7 @@ expand_omp_target (struct omp_region *region) enum built_in_function start_ix; location_t clause_loc; unsigned int flags_i = 0; + bool oacc_kernels_p = false; switch (gimple_omp_target_kind (entry_stmt)) { @@ -13144,8 +13179,10 @@ expand_omp_target (struct omp_region *region) start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA; flags_i |= GOMP_TARGET_FLAG_EXIT_DATA; break; - case GF_OMP_TARGET_KIND_OACC_PARALLEL: case GF_OMP_TARGET_KIND_OACC_KERNELS: + oacc_kernels_p = true; + /* FALLTHROUGH */ + case GF_OMP_TARGET_KIND_OACC_PARALLEL: start_ix = BUILT_IN_GOACC_PARALLEL; break; case GF_OMP_TARGET_KIND_OACC_DATA: @@ -13304,7 +13341,7 @@ expand_omp_target (struct omp_region *region) break; case BUILT_IN_GOACC_PARALLEL: { - set_oacc_fn_attrib (child_fn, clauses, &args); + set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args); tagging = true; } /* FALLTHRU */ @@ -20202,17 +20239,17 @@ oacc_xform_loop (gcall *call) } /* Validate and update the dimensions for offloaded FN. ATTRS is the - raw attribute. DIMS is an array of dimensions, which is returned. - Returns the function level dimensionality -- the level at which an - offload routine wishes to partition a loop. */ + raw attribute. DIMS is an array of dimensions, which is filled in. + LEVEL is the partitioning level of a routine, or -1 for an offload + region itself. */ -static int -oacc_validate_dims (tree fn, tree attrs, int *dims) +static void +oacc_validate_dims (tree fn, tree attrs, int *dims, int level) { tree purpose[GOMP_DIM_MAX]; unsigned ix; tree pos = TREE_VALUE (attrs); - int fn_level = -1; + bool is_kernel = oacc_fn_attrib_kernels_p (attrs); /* Make sure the attribute creator attached the dimension information. */ @@ -20221,21 +20258,12 @@ oacc_validate_dims (tree fn, tree attrs, int *dims) for (ix = 0; ix != GOMP_DIM_MAX; ix++) { purpose[ix] = TREE_PURPOSE (pos); - - if (purpose[ix]) - { - if (integer_zerop (purpose[ix])) - fn_level = ix + 1; - else if (fn_level < 0) - fn_level = ix; - } - tree val = TREE_VALUE (pos); dims[ix] = val ? TREE_INT_CST_LOW (val) : -1; pos = TREE_CHAIN (pos); } - bool changed = targetm.goacc.validate_dims (fn, dims, fn_level); + bool changed = targetm.goacc.validate_dims (fn, dims, level); /* Default anything left to 1. */ for (ix = 0; ix != GOMP_DIM_MAX; ix++) @@ -20250,13 +20278,15 @@ oacc_validate_dims (tree fn, tree attrs, int *dims) /* Replace the attribute with new values. */ pos = NULL_TREE; for (ix = GOMP_DIM_MAX; ix--;) - pos = tree_cons (purpose[ix], - build_int_cst (integer_type_node, dims[ix]), - pos); + { + pos = tree_cons (purpose[ix], + build_int_cst (integer_type_node, dims[ix]), + pos); + if (is_kernel) + TREE_PUBLIC (pos) = 1; + } replace_oacc_fn_attrib (fn, pos); } - - return fn_level; } /* Create an empty OpenACC loop structure at LOC. */ @@ -20327,8 +20357,7 @@ static void new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs) { oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call)); - int dims[GOMP_DIM_MAX]; - int level = oacc_validate_dims (decl, attrs, dims); + int level = oacc_fn_attrib_level (attrs); gcc_assert (level >= 0); @@ -20924,18 +20953,35 @@ static unsigned int execute_oacc_device_lower () { tree attrs = get_oacc_fn_attrib (current_function_decl); - int dims[GOMP_DIM_MAX]; if (!attrs) /* Not an offloaded function. */ return 0; - int fn_level = oacc_validate_dims (current_function_decl, attrs, dims); - /* Discover, partition and process the loops. */ oacc_loop *loops = oacc_loop_discovery (); + int fn_level = oacc_fn_attrib_level (attrs); + + if (dump_file) + fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs) + ? "Function is kernels offload\n" + : fn_level < 0 ? "Function is parallel offload\n" + : "Function is routine level %d\n", fn_level); + unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0; oacc_loop_partition (loops, outer_mask); + + int dims[GOMP_DIM_MAX]; + oacc_validate_dims (current_function_decl, attrs, dims, fn_level); + + if (dump_file) + { + const char *comma = "Compute dimensions ["; + for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ") + fprintf (dump_file, "%s%d", comma, dims[ix]); + fprintf (dump_file, "]\n"); + } + oacc_loop_process (loops); if (dump_file) { diff --git a/gcc/omp-low.h b/gcc/omp-low.h index 64caef8db69..b1f7885da0e 100644 --- a/gcc/omp-low.h +++ b/gcc/omp-low.h @@ -33,7 +33,8 @@ extern tree omp_member_access_dummy_var (tree); extern void replace_oacc_fn_attrib (tree, tree); extern tree build_oacc_routine_dims (tree); extern tree get_oacc_fn_attrib (tree); -extern void set_oacc_fn_attrib (tree, tree, vec *); +extern void set_oacc_fn_attrib (tree, tree, bool, vec *); +extern bool oacc_fn_attrib_kernels_p (tree); extern int get_oacc_ifn_dim_arg (const gimple *); extern int get_oacc_fn_dim_size (tree, int); diff --git a/gcc/testsuite/gcc.dg/ipa/inline-9.c b/gcc/testsuite/gcc.dg/ipa/inline-9.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 52dfc254e62..139e38c65d9 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -2041,7 +2041,7 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data, tree clause = build_omp_clause (loc, OMP_CLAUSE_NUM_GANGS); OMP_CLAUSE_NUM_GANGS_EXPR (clause) = build_int_cst (integer_type_node, n_threads); - set_oacc_fn_attrib (cfun->decl, clause, NULL); + set_oacc_fn_attrib (cfun->decl, clause, true, NULL); } else { diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index de09aa989f2..bdbade5e9ab 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -154,12 +154,7 @@ gate_oacc_kernels (function *fn) tree oacc_function_attr = get_oacc_fn_attrib (fn->decl); if (oacc_function_attr == NULL_TREE) return false; - - tree val = TREE_VALUE (oacc_function_attr); - while (val != NULL_TREE && TREE_VALUE (val) == NULL_TREE) - val = TREE_CHAIN (val); - - if (val != NULL_TREE) + if (!oacc_fn_attrib_kernels_p (oacc_function_attr)) return false; struct loop *loop;