From d34083a16b51c85b49092b0a5d9d444750f32134 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 11 Feb 2022 11:08:57 +0100 Subject: [PATCH] middle-end/104497 - gimplification of vector indexing The following attempts to address gimplification of ... = VIEW_CONVERT_EXPR((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(inv)[i] : VIEW_CONVERT_EXPR(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 PR middle-end/104497 * gimplify.c (gimplify_compound_lval): Make sure the base is a non-register if needed and possible. * c-c++-common/torture/pr104497.c: New testcase. --- gcc/gimplify.c | 11 +++++++++++ gcc/testsuite/c-c++-common/torture/pr104497.c | 12 ++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/torture/pr104497.c diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9a034326ecf..d6c39500727 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -245,6 +245,7 @@ static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool); static hash_map *oacc_declare_returns; static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *, bool (*) (tree), fallback_t, bool); +static void prepare_gimple_addressable (tree *, gimple_seq *); /* Shorter alias name for the above function for use in gimplify.c only. */ @@ -2979,6 +2980,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, So we do this in three steps. First we deal with the annotations for any variables in the components, then we gimplify the base, then we gimplify any indices, from left to right. */ + + bool need_non_reg = false; for (i = expr_stack.length () - 1; i >= 0; i--) { tree t = expr_stack[i]; @@ -3034,6 +3037,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, is_gimple_reg, fb_rvalue); ret = MIN (ret, tret); } + need_non_reg = true; } else if (TREE_CODE (t) == COMPONENT_REF) { @@ -3065,6 +3069,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, is_gimple_reg, fb_rvalue); ret = MIN (ret, tret); } + need_non_reg = true; } } @@ -3075,6 +3080,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, fallback | fb_lvalue); 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); + /* And finally, the indices and operands of ARRAY_REF. During this loop we also remove any useless conversions. */ for (; expr_stack.length () > 0; ) diff --git a/gcc/testsuite/c-c++-common/torture/pr104497.c b/gcc/testsuite/c-c++-common/torture/pr104497.c new file mode 100644 index 00000000000..c63fc021e03 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr104497.c @@ -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; +} -- 2.43.0