Message ID | mptzgcoayyz.fsf@arm.com |
---|---|
State | New |
Headers | show |
Series | gomp: Various fixes for SVE types [PR101018] | expand |
Ping Richard Sandiford <richard.sandiford@arm.com> writes: > Various parts of the omp code checked whether the size of a decl > was an INTEGER_CST in order to determine whether the decl was > variable-sized or not. If it was variable-sized, it was expected > to have a DECL_VALUE_EXPR replacement, as for VLAs. > > This patch uses poly_int_tree_p instead, so that variable-length > SVE vectors are treated like constant-length vectors. This means > that some structures become poly_int-sized, with some fields at > poly_int offsets, but we already have code to handle that. > > An alternative would have been to handle the data via indirection > instead. However, that's likely to be more complicated, and it > would contradict is_variable_sized, which already uses a check > for TREE_CONSTANT rather than INTEGER_CST. > > gimple_add_tmp_var should probably not add a safelen of 1 > for SVE vectors, but that's really a separate thing and might > be hard to test. > > Tested on aarch64-linux-gnu. OK to install? > > Richard > > > gcc/ > PR middle-end/101018 > * poly-int.h (can_and_p): New function. > * fold-const.cc (poly_int_binop): Use it to optimize BIT_AND_EXPRs > involving POLY_INT_CSTs. > * expr.cc (get_inner_reference): Fold poly_uint64 size_trees > into the constant bitsize. > * gimplify.cc (gimplify_bind_expr): Use poly_int_tree_p instead > of INTEGER_CST when checking for constant-sized omp data. > (omp_add_variable): Likewise. > (omp_notice_variable): Likewise. > (gimplify_adjust_omp_clauses_1): Likewise. > (gimplify_adjust_omp_clauses): Likewise. > * omp-low.cc (scan_sharing_clauses): Likewise. > (lower_omp_target): Likewise. > > gcc/testsuite/ > PR middle-end/101018 > * gcc.target/aarch64/sve/acle/pr101018-1.c: New test. > * gcc.target/aarch64/sve/acle/pr101018-2.c: Likewise > --- > gcc/expr.cc | 4 +-- > gcc/fold-const.cc | 7 +++++ > gcc/gimplify.cc | 23 ++++++++-------- > gcc/omp-low.cc | 10 +++---- > gcc/poly-int.h | 19 +++++++++++++ > .../aarch64/sve/acle/general/pr101018-1.c | 27 +++++++++++++++++++ > .../aarch64/sve/acle/general/pr101018-2.c | 23 ++++++++++++++++ > 7 files changed, 94 insertions(+), 19 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > > diff --git a/gcc/expr.cc b/gcc/expr.cc > index d9407432ea5..a304c583d16 100644 > --- a/gcc/expr.cc > +++ b/gcc/expr.cc > @@ -7941,10 +7941,10 @@ get_inner_reference (tree exp, poly_int64_pod *pbitsize, > > if (size_tree != 0) > { > - if (! tree_fits_uhwi_p (size_tree)) > + if (! tree_fits_poly_uint64_p (size_tree)) > mode = BLKmode, *pbitsize = -1; > else > - *pbitsize = tree_to_uhwi (size_tree); > + *pbitsize = tree_to_poly_uint64 (size_tree); > } > > *preversep = reverse_storage_order_for_component_p (exp); > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc > index b89cac91cae..000600017e2 100644 > --- a/gcc/fold-const.cc > +++ b/gcc/fold-const.cc > @@ -1183,6 +1183,13 @@ poly_int_binop (poly_wide_int &res, enum tree_code code, > return false; > break; > > + case BIT_AND_EXPR: > + if (TREE_CODE (arg2) != INTEGER_CST > + || !can_and_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), > + &res)) > + return false; > + break; > + > case BIT_IOR_EXPR: > if (TREE_CODE (arg2) != INTEGER_CST > || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), > diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc > index f06ce3cc77a..096738c8ed4 100644 > --- a/gcc/gimplify.cc > +++ b/gcc/gimplify.cc > @@ -7352,7 +7352,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) > /* When adding a variable-sized variable, we have to handle all sorts > of additional bits of data: the pointer replacement variable, and > the parameters of the type. */ > - if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl))) > { > /* Add the pointer replacement variable as PRIVATE if the variable > replacement is private, else FIRSTPRIVATE since we'll need the > @@ -8002,7 +8002,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) > && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN > && DECL_SIZE (decl)) > { > - if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + tree size; > + if (!poly_int_tree_p (DECL_SIZE (decl))) > { > splay_tree_node n2; > tree t = DECL_VALUE_EXPR (decl); > @@ -8013,16 +8014,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) > n2->value |= GOVD_SEEN; > } > else if (omp_privatize_by_reference (decl) > - && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))) > - && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) > - != INTEGER_CST)) > + && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) > + && !poly_int_tree_p (size)) > { > splay_tree_node n2; > - tree t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))); > - gcc_assert (DECL_P (t)); > - n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); > + gcc_assert (DECL_P (size)); > + n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size); > if (n2) > - omp_notice_variable (ctx, t, true); > + omp_notice_variable (ctx, size, true); > } > } > > @@ -12417,7 +12416,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) > if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0) > OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1; > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -12826,7 +12825,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, > } > } > else if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST > + && !poly_int_tree_p (DECL_SIZE (decl)) > && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER > && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER > && (OMP_CLAUSE_MAP_KIND (c) > @@ -12886,7 +12885,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, > if (!DECL_P (decl)) > break; > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc > index 82a93d00f67..6203fab5096 100644 > --- a/gcc/omp-low.cc > +++ b/gcc/omp-low.cc > @@ -1454,7 +1454,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > else > install_var_field (decl, false, 11, ctx); > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -1657,7 +1657,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > if (DECL_P (decl)) > { > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -1899,7 +1899,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > = remap_type (TREE_TYPE (decl), &ctx->cb); > } > else if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -12838,7 +12838,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) > } > > if (DECL_SIZE (var) > - && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (var))) > { > tree var2 = DECL_VALUE_EXPR (var); > gcc_assert (TREE_CODE (var2) == INDIRECT_REF); > @@ -13165,7 +13165,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) > else > { > if (DECL_SIZE (ovar) > - && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (ovar))) > { > tree ovar2 = DECL_VALUE_EXPR (ovar); > gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF); > diff --git a/gcc/poly-int.h b/gcc/poly-int.h > index d085544a57e..672db698dcc 100644 > --- a/gcc/poly-int.h > +++ b/gcc/poly-int.h > @@ -1977,6 +1977,25 @@ known_alignment (const poly_int_pod<N, Ca> &a) > return r & -r; > } > > +/* Return true if we can compute A & B at compile time, storing the > + result in RES if so. */ > + > +template<unsigned int N, typename Ca, typename Cb, typename Cr> > +inline typename if_nonpoly<Cb, bool>::type > +can_and_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result) > +{ > + /* Coefficients 1 and above must be a multiple of something greater > + than ~B. */ > + typedef POLY_INT_TYPE (Ca) int_type; > + if (N >= 2) > + for (unsigned int i = 1; i < N; i++) > + if ((-(a.coeffs[i] & -a.coeffs[i]) & ~b) != int_type (0)) > + return false; > + *result = a; > + result->coeffs[0] &= b; > + return true; > +} > + > /* Return true if we can compute A | B at compile time, storing the > result in RES if so. */ > > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > new file mode 100644 > index 00000000000..7592ad4c12e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > @@ -0,0 +1,27 @@ > +/* { dg-options "-O -fopenmp" } */ > + > +#include <stdint.h> > +#include <arm_sve.h> > + > +extern long N; > +extern double *a, *b, *c; > + > +void tuned_STREAM_Triad(double scalar) > +{ > + const uint64_t el = svcntd(); > + const svfloat64_t vscalar = svdup_n_f64(scalar); > + const int Nadj = N/el; > + int j; > + > +#pragma omp parallel for > + for (j = 0; j < Nadj; j ++) { > + svfloat64_t va, vb, vc; > + vb = svld1_vnum_f64(svptrue_b64(), b, j); > + vc = svld1_vnum_f64(svptrue_b64(), c, j); > + va = svmla_f64_z(svptrue_b64(), vb , vscalar, vc ); > + svst1_vnum_f64(svptrue_b64(), a, j+0, va); > + } > + > + for (j = Nadj*el ; j < N ; j++) > + a[j] = b[j] + scalar * c[j]; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > new file mode 100644 > index 00000000000..eee9c9f7e2b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > @@ -0,0 +1,23 @@ > +/* { dg-options "-O -fopenmp" } */ > + > +#include <arm_sve.h> > + > +void ext(void *); > +svfloat32_t ext2(); > + > +void > +foo (float32_t *ptr) > +{ > + svfloat32_t vec; > + /* These directives are mostly nonsense, but they shouldn't ICE. */ > + #pragma omp target data use_device_addr(vec) > + ext(&vec); > + #pragma omp target map(to:vec) > + ext(&vec); > + #pragma omp target defaultmap(none) firstprivate(vec) > + ext(&vec); > + #pragma omp target > + ext(&vec); > + #pragma omp target update to(vec) > + vec = ext2(); > +}
Ping^2 Richard Sandiford <richard.sandiford@arm.com> writes: > [I posted this late in stage 4 as an RFC, but it wasn't suitable for > GCC 12 at that point. I kind-of dropped the ball after that, sorry.] > > Various parts of the omp code checked whether the size of a decl > was an INTEGER_CST in order to determine whether the decl was > variable-sized or not. If it was variable-sized, it was expected > to have a DECL_VALUE_EXPR replacement, as for VLAs. > > This patch uses poly_int_tree_p instead, so that variable-length > SVE vectors are treated like constant-length vectors. This means > that some structures become poly_int-sized, with some fields at > poly_int offsets, but we already have code to handle that. > > An alternative would have been to handle the data via indirection > instead. However, that's likely to be more complicated, and it > would contradict is_variable_sized, which already uses a check > for TREE_CONSTANT rather than INTEGER_CST. > > gimple_add_tmp_var should probably not add a safelen of 1 > for SVE vectors, but that's really a separate thing and might > be hard to test. > > Tested on aarch64-linux-gnu. OK to install? > > Richard > > > gcc/ > PR middle-end/101018 > * poly-int.h (can_and_p): New function. > * fold-const.cc (poly_int_binop): Use it to optimize BIT_AND_EXPRs > involving POLY_INT_CSTs. > * expr.cc (get_inner_reference): Fold poly_uint64 size_trees > into the constant bitsize. > * gimplify.cc (gimplify_bind_expr): Use poly_int_tree_p instead > of INTEGER_CST when checking for constant-sized omp data. > (omp_add_variable): Likewise. > (omp_notice_variable): Likewise. > (gimplify_adjust_omp_clauses_1): Likewise. > (gimplify_adjust_omp_clauses): Likewise. > * omp-low.cc (scan_sharing_clauses): Likewise. > (lower_omp_target): Likewise. > > gcc/testsuite/ > PR middle-end/101018 > * gcc.target/aarch64/sve/acle/pr101018-1.c: New test. > * gcc.target/aarch64/sve/acle/pr101018-2.c: Likewise > --- > gcc/expr.cc | 4 +-- > gcc/fold-const.cc | 7 +++++ > gcc/gimplify.cc | 23 ++++++++-------- > gcc/omp-low.cc | 10 +++---- > gcc/poly-int.h | 19 +++++++++++++ > .../aarch64/sve/acle/general/pr101018-1.c | 27 +++++++++++++++++++ > .../aarch64/sve/acle/general/pr101018-2.c | 23 ++++++++++++++++ > 7 files changed, 94 insertions(+), 19 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > > diff --git a/gcc/expr.cc b/gcc/expr.cc > index d9407432ea5..a304c583d16 100644 > --- a/gcc/expr.cc > +++ b/gcc/expr.cc > @@ -7941,10 +7941,10 @@ get_inner_reference (tree exp, poly_int64_pod *pbitsize, > > if (size_tree != 0) > { > - if (! tree_fits_uhwi_p (size_tree)) > + if (! tree_fits_poly_uint64_p (size_tree)) > mode = BLKmode, *pbitsize = -1; > else > - *pbitsize = tree_to_uhwi (size_tree); > + *pbitsize = tree_to_poly_uint64 (size_tree); > } > > *preversep = reverse_storage_order_for_component_p (exp); > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc > index b89cac91cae..000600017e2 100644 > --- a/gcc/fold-const.cc > +++ b/gcc/fold-const.cc > @@ -1183,6 +1183,13 @@ poly_int_binop (poly_wide_int &res, enum tree_code code, > return false; > break; > > + case BIT_AND_EXPR: > + if (TREE_CODE (arg2) != INTEGER_CST > + || !can_and_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), > + &res)) > + return false; > + break; > + > case BIT_IOR_EXPR: > if (TREE_CODE (arg2) != INTEGER_CST > || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), > diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc > index f06ce3cc77a..096738c8ed4 100644 > --- a/gcc/gimplify.cc > +++ b/gcc/gimplify.cc > @@ -7352,7 +7352,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) > /* When adding a variable-sized variable, we have to handle all sorts > of additional bits of data: the pointer replacement variable, and > the parameters of the type. */ > - if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl))) > { > /* Add the pointer replacement variable as PRIVATE if the variable > replacement is private, else FIRSTPRIVATE since we'll need the > @@ -8002,7 +8002,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) > && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN > && DECL_SIZE (decl)) > { > - if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + tree size; > + if (!poly_int_tree_p (DECL_SIZE (decl))) > { > splay_tree_node n2; > tree t = DECL_VALUE_EXPR (decl); > @@ -8013,16 +8014,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) > n2->value |= GOVD_SEEN; > } > else if (omp_privatize_by_reference (decl) > - && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))) > - && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) > - != INTEGER_CST)) > + && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) > + && !poly_int_tree_p (size)) > { > splay_tree_node n2; > - tree t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))); > - gcc_assert (DECL_P (t)); > - n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); > + gcc_assert (DECL_P (size)); > + n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size); > if (n2) > - omp_notice_variable (ctx, t, true); > + omp_notice_variable (ctx, size, true); > } > } > > @@ -12417,7 +12416,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) > if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0) > OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1; > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -12826,7 +12825,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, > } > } > else if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST > + && !poly_int_tree_p (DECL_SIZE (decl)) > && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER > && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER > && (OMP_CLAUSE_MAP_KIND (c) > @@ -12886,7 +12885,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, > if (!DECL_P (decl)) > break; > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc > index 82a93d00f67..6203fab5096 100644 > --- a/gcc/omp-low.cc > +++ b/gcc/omp-low.cc > @@ -1454,7 +1454,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > else > install_var_field (decl, false, 11, ctx); > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -1657,7 +1657,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > if (DECL_P (decl)) > { > if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -1899,7 +1899,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) > = remap_type (TREE_TYPE (decl), &ctx->cb); > } > else if (DECL_SIZE (decl) > - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (decl))) > { > tree decl2 = DECL_VALUE_EXPR (decl); > gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); > @@ -12838,7 +12838,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) > } > > if (DECL_SIZE (var) > - && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (var))) > { > tree var2 = DECL_VALUE_EXPR (var); > gcc_assert (TREE_CODE (var2) == INDIRECT_REF); > @@ -13165,7 +13165,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) > else > { > if (DECL_SIZE (ovar) > - && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST) > + && !poly_int_tree_p (DECL_SIZE (ovar))) > { > tree ovar2 = DECL_VALUE_EXPR (ovar); > gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF); > diff --git a/gcc/poly-int.h b/gcc/poly-int.h > index d085544a57e..672db698dcc 100644 > --- a/gcc/poly-int.h > +++ b/gcc/poly-int.h > @@ -1977,6 +1977,25 @@ known_alignment (const poly_int_pod<N, Ca> &a) > return r & -r; > } > > +/* Return true if we can compute A & B at compile time, storing the > + result in RES if so. */ > + > +template<unsigned int N, typename Ca, typename Cb, typename Cr> > +inline typename if_nonpoly<Cb, bool>::type > +can_and_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result) > +{ > + /* Coefficients 1 and above must be a multiple of something greater > + than ~B. */ > + typedef POLY_INT_TYPE (Ca) int_type; > + if (N >= 2) > + for (unsigned int i = 1; i < N; i++) > + if ((-(a.coeffs[i] & -a.coeffs[i]) & ~b) != int_type (0)) > + return false; > + *result = a; > + result->coeffs[0] &= b; > + return true; > +} > + > /* Return true if we can compute A | B at compile time, storing the > result in RES if so. */ > > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > new file mode 100644 > index 00000000000..7592ad4c12e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c > @@ -0,0 +1,27 @@ > +/* { dg-options "-O -fopenmp" } */ > + > +#include <stdint.h> > +#include <arm_sve.h> > + > +extern long N; > +extern double *a, *b, *c; > + > +void tuned_STREAM_Triad(double scalar) > +{ > + const uint64_t el = svcntd(); > + const svfloat64_t vscalar = svdup_n_f64(scalar); > + const int Nadj = N/el; > + int j; > + > +#pragma omp parallel for > + for (j = 0; j < Nadj; j ++) { > + svfloat64_t va, vb, vc; > + vb = svld1_vnum_f64(svptrue_b64(), b, j); > + vc = svld1_vnum_f64(svptrue_b64(), c, j); > + va = svmla_f64_z(svptrue_b64(), vb , vscalar, vc ); > + svst1_vnum_f64(svptrue_b64(), a, j+0, va); > + } > + > + for (j = Nadj*el ; j < N ; j++) > + a[j] = b[j] + scalar * c[j]; > +} > diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > new file mode 100644 > index 00000000000..eee9c9f7e2b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c > @@ -0,0 +1,23 @@ > +/* { dg-options "-O -fopenmp" } */ > + > +#include <arm_sve.h> > + > +void ext(void *); > +svfloat32_t ext2(); > + > +void > +foo (float32_t *ptr) > +{ > + svfloat32_t vec; > + /* These directives are mostly nonsense, but they shouldn't ICE. */ > + #pragma omp target data use_device_addr(vec) > + ext(&vec); > + #pragma omp target map(to:vec) > + ext(&vec); > + #pragma omp target defaultmap(none) firstprivate(vec) > + ext(&vec); > + #pragma omp target > + ext(&vec); > + #pragma omp target update to(vec) > + vec = ext2(); > +}
diff --git a/gcc/expr.cc b/gcc/expr.cc index d9407432ea5..a304c583d16 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -7941,10 +7941,10 @@ get_inner_reference (tree exp, poly_int64_pod *pbitsize, if (size_tree != 0) { - if (! tree_fits_uhwi_p (size_tree)) + if (! tree_fits_poly_uint64_p (size_tree)) mode = BLKmode, *pbitsize = -1; else - *pbitsize = tree_to_uhwi (size_tree); + *pbitsize = tree_to_poly_uint64 (size_tree); } *preversep = reverse_storage_order_for_component_p (exp); diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index b89cac91cae..000600017e2 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -1183,6 +1183,13 @@ poly_int_binop (poly_wide_int &res, enum tree_code code, return false; break; + case BIT_AND_EXPR: + if (TREE_CODE (arg2) != INTEGER_CST + || !can_and_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), + &res)) + return false; + break; + case BIT_IOR_EXPR: if (TREE_CODE (arg2) != INTEGER_CST || !can_ior_p (wi::to_poly_wide (arg1), wi::to_wide (arg2), diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index f06ce3cc77a..096738c8ed4 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -7352,7 +7352,7 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) /* When adding a variable-sized variable, we have to handle all sorts of additional bits of data: the pointer replacement variable, and the parameters of the type. */ - if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl))) { /* Add the pointer replacement variable as PRIVATE if the variable replacement is private, else FIRSTPRIVATE since we'll need the @@ -8002,7 +8002,8 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN && DECL_SIZE (decl)) { - if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + tree size; + if (!poly_int_tree_p (DECL_SIZE (decl))) { splay_tree_node n2; tree t = DECL_VALUE_EXPR (decl); @@ -8013,16 +8014,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) n2->value |= GOVD_SEEN; } else if (omp_privatize_by_reference (decl) - && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))) - && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) - != INTEGER_CST)) + && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))) + && !poly_int_tree_p (size)) { splay_tree_node n2; - tree t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))); - gcc_assert (DECL_P (t)); - n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t); + gcc_assert (DECL_P (size)); + n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size); if (n2) - omp_notice_variable (ctx, t, true); + omp_notice_variable (ctx, size, true); } } @@ -12417,7 +12416,7 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data) if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0) OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1; if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); @@ -12826,7 +12825,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, } } else if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST + && !poly_int_tree_p (DECL_SIZE (decl)) && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER && (OMP_CLAUSE_MAP_KIND (c) @@ -12886,7 +12885,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, if (!DECL_P (decl)) break; if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index 82a93d00f67..6203fab5096 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -1454,7 +1454,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) else install_var_field (decl, false, 11, ctx); if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); @@ -1657,7 +1657,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) if (DECL_P (decl)) { if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); @@ -1899,7 +1899,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) = remap_type (TREE_TYPE (decl), &ctx->cb); } else if (DECL_SIZE (decl) - && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (decl))) { tree decl2 = DECL_VALUE_EXPR (decl); gcc_assert (TREE_CODE (decl2) == INDIRECT_REF); @@ -12838,7 +12838,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) } if (DECL_SIZE (var) - && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (var))) { tree var2 = DECL_VALUE_EXPR (var); gcc_assert (TREE_CODE (var2) == INDIRECT_REF); @@ -13165,7 +13165,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) else { if (DECL_SIZE (ovar) - && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST) + && !poly_int_tree_p (DECL_SIZE (ovar))) { tree ovar2 = DECL_VALUE_EXPR (ovar); gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF); diff --git a/gcc/poly-int.h b/gcc/poly-int.h index d085544a57e..672db698dcc 100644 --- a/gcc/poly-int.h +++ b/gcc/poly-int.h @@ -1977,6 +1977,25 @@ known_alignment (const poly_int_pod<N, Ca> &a) return r & -r; } +/* Return true if we can compute A & B at compile time, storing the + result in RES if so. */ + +template<unsigned int N, typename Ca, typename Cb, typename Cr> +inline typename if_nonpoly<Cb, bool>::type +can_and_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result) +{ + /* Coefficients 1 and above must be a multiple of something greater + than ~B. */ + typedef POLY_INT_TYPE (Ca) int_type; + if (N >= 2) + for (unsigned int i = 1; i < N; i++) + if ((-(a.coeffs[i] & -a.coeffs[i]) & ~b) != int_type (0)) + return false; + *result = a; + result->coeffs[0] &= b; + return true; +} + /* Return true if we can compute A | B at compile time, storing the result in RES if so. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c new file mode 100644 index 00000000000..7592ad4c12e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-1.c @@ -0,0 +1,27 @@ +/* { dg-options "-O -fopenmp" } */ + +#include <stdint.h> +#include <arm_sve.h> + +extern long N; +extern double *a, *b, *c; + +void tuned_STREAM_Triad(double scalar) +{ + const uint64_t el = svcntd(); + const svfloat64_t vscalar = svdup_n_f64(scalar); + const int Nadj = N/el; + int j; + +#pragma omp parallel for + for (j = 0; j < Nadj; j ++) { + svfloat64_t va, vb, vc; + vb = svld1_vnum_f64(svptrue_b64(), b, j); + vc = svld1_vnum_f64(svptrue_b64(), c, j); + va = svmla_f64_z(svptrue_b64(), vb , vscalar, vc ); + svst1_vnum_f64(svptrue_b64(), a, j+0, va); + } + + for (j = Nadj*el ; j < N ; j++) + a[j] = b[j] + scalar * c[j]; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c new file mode 100644 index 00000000000..eee9c9f7e2b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr101018-2.c @@ -0,0 +1,23 @@ +/* { dg-options "-O -fopenmp" } */ + +#include <arm_sve.h> + +void ext(void *); +svfloat32_t ext2(); + +void +foo (float32_t *ptr) +{ + svfloat32_t vec; + /* These directives are mostly nonsense, but they shouldn't ICE. */ + #pragma omp target data use_device_addr(vec) + ext(&vec); + #pragma omp target map(to:vec) + ext(&vec); + #pragma omp target defaultmap(none) firstprivate(vec) + ext(&vec); + #pragma omp target + ext(&vec); + #pragma omp target update to(vec) + vec = ext2(); +}