middle-end/104497 - gimplification of vector indexing

The following attempts to address gimplification of

   ... = VIEW_CONVERT_EXPR<int[4]>((i & 1) != 0 ? inv : src)[i];

which is problematic since gimplifying the base object
? inv : src produces a register temporary but GIMPLE does not
really support a register as a base for an ARRAY_REF (even
though that's not strictly validated it seems as can be seen
at -O0).  Interestingly the C++ frontend avoids this issue
by emitting the following GENERIC instead:

   ... = (i & 1) != 0 ? VIEW_CONVERT_EXPR<int[4]>(inv)[i] : VIEW_CONVERT_EXPR<int[4]>(src)[i];

The proposed patch below fixes things up when using an rvalue
as the base is OK by emitting a copy from a register base to a
non-register one.  The ?: as lvalue extension seems to be gone
for C, C++ again unwraps the COND_EXPR in that case.

2022-02-11  Richard Biener  <rguenther@suse.de>

	PR middle-end/104497
	* gimplify.cc (gimplify_compound_lval): Make sure the
	base is a non-register if needed and possible.

	* c-c++-common/torture/pr104497.c: New testcase.
This commit is contained in:
Richard Biener 2022-02-11 11:08:57 +01:00
parent 0d31c8ec3f
commit 3f10e0d50b
2 changed files with 26 additions and 3 deletions

View File

@ -250,6 +250,7 @@ static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
static hash_map<tree, tree> *oacc_declare_returns; static hash_map<tree, tree> *oacc_declare_returns;
static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *, static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
bool (*) (tree), fallback_t, bool); bool (*) (tree), fallback_t, bool);
static void prepare_gimple_addressable (tree *, gimple_seq *);
/* Shorter alias name for the above function for use in gimplify.cc /* Shorter alias name for the above function for use in gimplify.cc
only. */ only. */
@ -3122,10 +3123,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
gimplified before gimplifying the size expressions. gimplified before gimplifying the size expressions.
So we do this in three steps. First we deal with variable So we do this in three steps. First we deal with variable
bounds, sizes, and positions, then we gimplify the base, bounds, sizes, and positions, then we gimplify the base and
then we deal with the annotations for any variables in the ensure it is memory if needed, then we deal with the annotations
components and any indices, from left to right. */ for any variables in the components and any indices, from left
to right. */
bool need_non_reg = false;
for (i = expr_stack.length () - 1; i >= 0; i--) for (i = expr_stack.length () - 1; i >= 0; i--)
{ {
tree t = expr_stack[i]; tree t = expr_stack[i];
@ -3161,6 +3164,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
TREE_OPERAND (t, 3) = elmt_size; TREE_OPERAND (t, 3) = elmt_size;
} }
} }
need_non_reg = true;
} }
else if (TREE_CODE (t) == COMPONENT_REF) else if (TREE_CODE (t) == COMPONENT_REF)
{ {
@ -3182,6 +3186,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
TREE_OPERAND (t, 2) = offset; TREE_OPERAND (t, 2) = offset;
} }
} }
need_non_reg = true;
} }
} }
@ -3192,6 +3197,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
fallback | fb_lvalue); fallback | fb_lvalue);
ret = MIN (ret, tret); ret = MIN (ret, tret);
/* Step 2a: if we have component references we do not support on
registers then make sure the base isn't a register. Of course
we can only do so if an rvalue is OK. */
if (need_non_reg && (fallback & fb_rvalue))
prepare_gimple_addressable (p, pre_p);
/* Step 3: gimplify size expressions and the indices and operands of /* Step 3: gimplify size expressions and the indices and operands of
ARRAY_REF. During this loop we also remove any useless conversions. */ ARRAY_REF. During this loop we also remove any useless conversions. */

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
typedef int __attribute__((vector_size(16))) vec_t;
vec_t src, inv, res;
void test(int i)
{
vec_t y={0};
y[i] = (i & 1 ? inv : src)[i];
res = y;
}