gomp: Various fixes for SVE types [PR101018]

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.

Co-authored-by: Tejas Belagod <tejas.belagod@arm.com>

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.
	* gimplify.cc (omp_notice_variable): Use poly_int_tree_p instead
	of INTEGER_CST when checking for constant-sized omp data.
	(gimplify_adjust_omp_clauses_1): Likewise.
	(gimplify_adjust_omp_clauses): Likewise.
	* omp-low.cc (scan_sharing_clauses): Likewise.
This commit is contained in:
Richard Sandiford 2023-05-12 10:33:25 +01:00 committed by Tejas Belagod
parent 2b809d6f4f
commit 001fb23ae4
4 changed files with 36 additions and 11 deletions

View file

@ -1284,6 +1284,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),

View file

@ -9301,7 +9301,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);
@ -9312,16 +9313,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);
}
}
@ -14581,7 +14580,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 (INDIRECT_REF_P (decl2));
@ -15322,7 +15321,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 (INDIRECT_REF_P (decl2));

View file

@ -1461,7 +1461,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 (INDIRECT_REF_P (decl2));

View file

@ -1906,6 +1906,25 @@ known_alignment (const poly_int<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<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. */