From: Nathan Sidwell Date: Thu, 5 Nov 2015 13:50:13 +0000 (+0000) Subject: target.def (goacc.dim_limit): New hook. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bd7519757549bb0f61433767be4587d1d287fbae;p=gcc.git target.def (goacc.dim_limit): New hook. * target.def (goacc.dim_limit): New hook. * targhooks.h (default_goacc_dim_limit): Declare. * doc/tm.texi.in (TARGET_GOACC_DIM_LIMIT): Add. * doc/tm.texi: Rebuilt. * omp-low.h (get_oacc_fn_dim_size, get_oacc_ifn_dim_arg): Declare. * omp-low.c (get_oacc_fn_dim_size, get_oacc_ifn_dim_arg): New. (default_goacc_dim_limit): New. * config/nvptx/nvptx.c (PTX_VECTOR_LENGTH, PTX_WORKER_LENGTH): New. (nvptx_goacc_dim_limit) New. (TARGET_GOACC_DIM_LIMIT): Override. * tree-vrp.c: Include omp-low.h, target.h. (extract_range_basic): Add handling for IFN_GOACC_DIM_SIZE & IFN_GOACC_DIM_POS. From-SVN: r229809 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7b238ba2c7..44e71f48d15 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2015-11-05 Nathan Sidwell + + * target.def (goacc.dim_limit): New hook. + * targhooks.h (default_goacc_dim_limit): Declare. + * doc/tm.texi.in (TARGET_GOACC_DIM_LIMIT): Add. + * doc/tm.texi: Rebuilt. + * omp-low.h (get_oacc_fn_dim_size, get_oacc_ifn_dim_arg): Declare. + * omp-low.c (get_oacc_fn_dim_size, get_oacc_ifn_dim_arg): New. + (default_goacc_dim_limit): New. + * config/nvptx/nvptx.c (PTX_VECTOR_LENGTH, PTX_WORKER_LENGTH): New. + (nvptx_goacc_dim_limit) New. + (TARGET_GOACC_DIM_LIMIT): Override. + * tree-vrp.c: Include omp-low.h, target.h. + (extract_range_basic): Add handling for IFN_GOACC_DIM_SIZE & + IFN_GOACC_DIM_POS. + 2015-11-05 Ilya Enkovich * tree-vect-generic.c (do_compare): Use -1 for true diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index dafb6954690..0204ad3383e 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -3499,6 +3499,25 @@ nvptx_goacc_validate_dims (tree ARG_UNUSED (decl), int *ARG_UNUSED (dims), return changed; } +/* Return maximum dimension size, or zero for unbounded. */ + +static int +nvptx_dim_limit (int axis) +{ + switch (axis) + { + case GOMP_DIM_WORKER: + return PTX_WORKER_LENGTH; + + case GOMP_DIM_VECTOR: + return PTX_VECTOR_LENGTH; + + default: + break; + } + return 0; +} + /* Determine whether fork & joins are needed. */ static bool @@ -4016,6 +4035,9 @@ nvptx_goacc_reduction (gcall *call) #undef TARGET_GOACC_VALIDATE_DIMS #define TARGET_GOACC_VALIDATE_DIMS nvptx_goacc_validate_dims +#undef TARGET_GOACC_DIM_LIMIT +#define TARGET_GOACC_DIM_LIMIT nvptx_dim_limit + #undef TARGET_GOACC_FORK_JOIN #define TARGET_GOACC_FORK_JOIN nvptx_goacc_fork_join diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 1e6baa0a080..f394db7d0a6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5777,6 +5777,11 @@ true, if changes have been made. You must override this hook to provide dimensions larger than 1. @end deftypefn +@deftypefn {Target Hook} int TARGET_GOACC_DIM_LIMIT (int @var{axis}) +This hook should return the maximum size of a particular dimension, +or zero if unbounded. +@end deftypefn + @deftypefn {Target Hook} bool TARGET_GOACC_FORK_JOIN (gcall *@var{call}, const int *@var{dims}, bool @var{is_fork}) This hook can be used to convert IFN_GOACC_FORK and IFN_GOACC_JOIN function calls to target-specific gimple, or indicate whether they diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 0529011cb61..d188c57b75c 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -4262,6 +4262,8 @@ address; but often a machine-dependent strategy can generate better code. @hook TARGET_GOACC_VALIDATE_DIMS +@hook TARGET_GOACC_DIM_LIMIT + @hook TARGET_GOACC_FORK_JOIN @hook TARGET_GOACC_REDUCTION diff --git a/gcc/omp-low.c b/gcc/omp-low.c index ac88fa58d7a..b72c3dd4249 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -12096,6 +12096,41 @@ get_oacc_fn_attrib (tree fn) return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn)); } +/* 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. */ + +int +get_oacc_fn_dim_size (tree fn, int axis) +{ + tree attrs = get_oacc_fn_attrib (fn); + + gcc_assert (axis < GOMP_DIM_MAX); + + tree dims = TREE_VALUE (attrs); + while (axis--) + dims = TREE_CHAIN (dims); + + int size = TREE_INT_CST_LOW (TREE_VALUE (dims)); + + return size; +} + +/* Extract the dimension axis from an IFN_GOACC_DIM_POS or + IFN_GOACC_DIM_SIZE call. */ + +int +get_oacc_ifn_dim_arg (const gimple *stmt) +{ + gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE + || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS); + tree arg = gimple_call_arg (stmt, 0); + HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg); + + gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX); + return (int) axis; +} + /* Expand the GIMPLE_OMP_TARGET starting at REGION. */ static void @@ -19015,6 +19050,18 @@ default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims, return changed; } +/* Default dimension bound is unknown on accelerator and 1 on host. */ + +int +default_goacc_dim_limit (int ARG_UNUSED (axis)) +{ +#ifdef ACCEL_COMPILER + return 0; +#else + return 1; +#endif +} + namespace { const pass_data pass_data_oacc_device_lower = diff --git a/gcc/omp-low.h b/gcc/omp-low.h index 2fb2028f6cf..ee0f8ac1ad5 100644 --- a/gcc/omp-low.h +++ b/gcc/omp-low.h @@ -31,6 +31,8 @@ extern bool make_gimple_omp_edges (basic_block, struct omp_region **, int *); extern void omp_finish_file (void); extern tree omp_member_access_dummy_var (tree); extern tree get_oacc_fn_attrib (tree); +extern int get_oacc_ifn_dim_arg (const gimple *); +extern int get_oacc_fn_dim_size (tree, int); extern GTY(()) vec *offload_funcs; extern GTY(()) vec *offload_vars; diff --git a/gcc/target.def b/gcc/target.def index 461af6b14d8..c7ec2929714 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1658,6 +1658,13 @@ provide dimensions larger than 1.", bool, (tree decl, int *dims, int fn_level), default_goacc_validate_dims) +DEFHOOK +(dim_limit, +"This hook should return the maximum size of a particular dimension,\n\ +or zero if unbounded.", +int, (int axis), +default_goacc_dim_limit) + DEFHOOK (fork_join, "This hook can be used to convert IFN_GOACC_FORK and IFN_GOACC_JOIN\n\ diff --git a/gcc/targhooks.h b/gcc/targhooks.h index c34e4ae052c..a8e7ebbd8ca 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -110,6 +110,7 @@ extern void default_destroy_cost_data (void *); /* OpenACC hooks. */ extern bool default_goacc_validate_dims (tree, int [], int); +extern int default_goacc_dim_limit (int); extern bool default_goacc_fork_join (gcall *, const int [], bool); extern void default_goacc_reduction (gcall *); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 807c6ecc804..c0b6cfc1444 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -55,8 +55,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-threadupdate.h" #include "tree-ssa-scopedtables.h" #include "tree-ssa-threadedge.h" - - +#include "omp-low.h" +#include "target.h" /* Range of values that can be associated with an SSA_NAME after VRP has executed. */ @@ -3973,7 +3973,9 @@ extract_range_basic (value_range *vr, gimple *stmt) else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt)) { enum tree_code subcode = ERROR_MARK; - switch (gimple_call_internal_fn (stmt)) + unsigned ifn_code = gimple_call_internal_fn (stmt); + + switch (ifn_code) { case IFN_UBSAN_CHECK_ADD: subcode = PLUS_EXPR; @@ -3984,6 +3986,28 @@ extract_range_basic (value_range *vr, gimple *stmt) case IFN_UBSAN_CHECK_MUL: subcode = MULT_EXPR; break; + case IFN_GOACC_DIM_SIZE: + case IFN_GOACC_DIM_POS: + /* Optimizing these two internal functions helps the loop + optimizer eliminate outer comparisons. Size is [1,N] + and pos is [0,N-1]. */ + { + bool is_pos = ifn_code == IFN_GOACC_DIM_POS; + int axis = get_oacc_ifn_dim_arg (stmt); + int size = get_oacc_fn_dim_size (current_function_decl, axis); + + if (!size) + /* If it's dynamic, the backend might know a hardware + limitation. */ + size = targetm.goacc.dim_limit (axis); + + tree type = TREE_TYPE (gimple_call_lhs (stmt)); + set_value_range (vr, VR_RANGE, + build_int_cst (type, is_pos ? 0 : 1), + size ? build_int_cst (type, size - is_pos) + : vrp_val_max (type), NULL); + } + return; default: break; }