https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101530

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org
             Status|NEW                         |ASSIGNED

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
If we stop walking in gimplify_compound_lval we still gimplify the tail in the
same way, not assigning the register typed BIT_FIELD_REF to a temporary.

A bit less degenerate testcase:

typedef int __attribute__((__vector_size__ (16))) V;
int
foo(V v, int i)
{
  return __builtin_shufflevector (v, v, 2, 3)[i];
}

We can't really simplify the original GENERIC much here:

  return VIEW_CONVERT_EXPR<int[2]>(BIT_FIELD_REF < VEC_PERM_EXPR < v , v , { 2,
3, 2, 3 } > , 64, 0>)[i];

the BIT_FIELD_REF is used to subset the vector, what we'd need to somehow
ensure is to force that to an rvalue.  I suppose that would be possible
if we'd wrap it in a TARGET_EXPR somehow.  At least the following works for me:

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 13341fa315e..4631d50c6f0 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1243,6 +1243,8 @@ c_build_shufflevector (location_t loc, tree v0, tree v1,
       tree lpartt = build_vector_type (TREE_TYPE (ret_type), mask.length ());
       ret = build3_loc (loc, BIT_FIELD_REF,
                        lpartt, ret, TYPE_SIZE (lpartt), bitsize_zero_node);
+      tree tem = create_tmp_var_raw (lpartt);
+      ret = build4 (TARGET_EXPR, lpartt, tem, ret, NULL_TREE, NULL_TREE);
     }

   if (!c_dialect_cxx () && !wrap)

Reply via email to