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)