diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 869685077c8..b208b470c0b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-11-17 Tom de Vries + + * cfgloop.h (struct loop): Add in_oacc_kernels_region field. + * omp-low.c (mark_loops_in_oacc_kernels_region): New function. + (expand_omp_target): Call mark_loops_in_oacc_kernels_region. + 2015-11-17 Bernd Schmidt * regrename.c (regrename_find_superclass): New function, code moved diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 6af68939eda..ee73bf994c1 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -191,6 +191,9 @@ struct GTY ((chain_next ("%h.next"))) loop { /* True if we should try harder to vectorize this loop. */ bool force_vectorize; + /* True if the loop is part of an oacc kernels region. */ + bool in_oacc_kernels_region; + /* For SIMD loops, this is a unique identifier of the loop, referenced by IFN_GOMP_SIMD_VF, IFN_GOMP_SIMD_LANE and IFN_GOMP_SIMD_LAST_LANE builtins. */ diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 97df42f28dd..b327abd490d 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1021,6 +1021,7 @@ copy_loop_info (struct loop *loop, struct loop *target) target->estimate_state = loop->estimate_state; target->warned_aggressive_loop_optimizations |= loop->warned_aggressive_loop_optimizations; + target->in_oacc_kernels_region = loop->in_oacc_kernels_region; } /* Copies copy of LOOP as subloop of TARGET loop, placing newly diff --git a/gcc/omp-low.c b/gcc/omp-low.c index efcc971b98a..830db75a0e6 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -12426,6 +12426,46 @@ get_oacc_ifn_dim_arg (const gimple *stmt) return (int) axis; } +/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending + at REGION_EXIT. */ + +static void +mark_loops_in_oacc_kernels_region (basic_block region_entry, + basic_block region_exit) +{ + struct loop *outer = region_entry->loop_father; + gcc_assert (region_exit == NULL || outer == region_exit->loop_father); + + /* Don't parallelize the kernels region if it contains more than one outer + loop. */ + unsigned int nr_outer_loops = 0; + struct loop *single_outer; + for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next) + { + gcc_assert (loop_outer (loop) == outer); + + if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry)) + continue; + + if (region_exit != NULL + && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit)) + continue; + + nr_outer_loops++; + single_outer = loop; + } + if (nr_outer_loops != 1) + return; + + for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner) + if (loop->next) + return; + + /* Mark the loops in the region. */ + for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner) + loop->in_oacc_kernels_region = true; +} + /* Expand the GIMPLE_OMP_TARGET starting at REGION. */ static void @@ -12481,6 +12521,9 @@ expand_omp_target (struct omp_region *region) entry_bb = region->entry; exit_bb = region->exit; + if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS) + mark_loops_in_oacc_kernels_region (region->entry, region->exit); + if (offloaded) { unsigned srcidx, dstidx, num;