The patch for PR63764 (accepts-invalid / ICE) caused us to generate worse code for rvalue vector indexing by forcing the vector to a temporary. It turns out this is not necessary if we alter the way the C/C++ FE lower the vector to perform the indexing operation from lowering to a pointer-to-element to lowering to an array using a VIEW_CONVERT_EXPR.
The alternate lowering has the advantage that the vector is not required to be addressable which should improve aliasing analysis. Not lowering to indirect accesses should also improve optimizations like value-numbering. There's the fallout that we need to make sure to convert back constant index array-refs to the canonical BIT_FIELD_REF form we use for vectors (see the gimple-fold.c hunk pattern-matching this). And there's the latent bug in update-address-taken which happily re-wrote a vector array-ref base into SSA form. Bootstrapped on x86_64-unknown-linux-gnu, testing still in progress. I'll happily defer to stage1 if you think that's better as I don't know any project that heavily makes use of GCCs vector extension and I'm not sure about our own testsuite coverage. Ok for trunk? Thanks, Richard. 2016-03-30 Richard Biener <rguent...@suse.de> PR middle-end/70434 c-family/ * c-common.c (convert_vector_to_pointer_for_subscript): Use a VIEW_CONVERT_EXPR to an array type. * tree-ssa.c (non_rewritable_mem_ref_base): Make sure to mark bases which are accessed with non-invariant indices. * gimple-fold.c (maybe_canonicalize_mem_ref_addr): Re-write constant index ARRAY_REFs of vectors into BIT_FIELD_REFs. Index: gcc/c-family/c-common.c =================================================================== *** gcc/c-family/c-common.c (revision 234545) --- gcc/c-family/c-common.c (working copy) *************** convert_vector_to_pointer_for_subscript *** 12448,12501 **** if (VECTOR_TYPE_P (TREE_TYPE (*vecp))) { tree type = TREE_TYPE (*vecp); - tree type1; ret = !lvalue_p (*vecp); if (TREE_CODE (index) == INTEGER_CST) if (!tree_fits_uhwi_p (index) || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type)) warning_at (loc, OPT_Warray_bounds, "index value is out of bound"); ! if (ret) ! { ! tree tmp = create_tmp_var_raw (type); ! DECL_SOURCE_LOCATION (tmp) = loc; ! *vecp = c_save_expr (*vecp); ! if (TREE_CODE (*vecp) == C_MAYBE_CONST_EXPR) ! { ! bool non_const = C_MAYBE_CONST_EXPR_NON_CONST (*vecp); ! *vecp = C_MAYBE_CONST_EXPR_EXPR (*vecp); ! *vecp ! = c_wrap_maybe_const (build4 (TARGET_EXPR, type, tmp, ! *vecp, NULL_TREE, NULL_TREE), ! non_const); ! } ! else ! *vecp = build4 (TARGET_EXPR, type, tmp, *vecp, ! NULL_TREE, NULL_TREE); ! SET_EXPR_LOCATION (*vecp, loc); ! c_common_mark_addressable_vec (tmp); ! } ! else ! c_common_mark_addressable_vec (*vecp); ! type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); ! type1 = build_pointer_type (TREE_TYPE (*vecp)); ! bool ref_all = TYPE_REF_CAN_ALIAS_ALL (type1); ! if (!ref_all ! && !DECL_P (*vecp)) ! { ! /* If the original vector isn't declared may_alias and it ! isn't a bare vector look if the subscripting would ! alias the vector we subscript, and if not, force ref-all. */ ! alias_set_type vecset = get_alias_set (*vecp); ! alias_set_type sset = get_alias_set (type); ! if (!alias_sets_must_conflict_p (sset, vecset) ! && !alias_set_subset_of (sset, vecset)) ! ref_all = true; ! } ! type = build_pointer_type_for_mode (type, ptr_mode, ref_all); ! *vecp = build1 (ADDR_EXPR, type1, *vecp); ! *vecp = convert (type, *vecp); } return ret; } --- 12448,12470 ---- if (VECTOR_TYPE_P (TREE_TYPE (*vecp))) { tree type = TREE_TYPE (*vecp); ret = !lvalue_p (*vecp); + if (TREE_CODE (index) == INTEGER_CST) if (!tree_fits_uhwi_p (index) || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type)) warning_at (loc, OPT_Warray_bounds, "index value is out of bound"); ! /* We are building an ARRAY_REF so mark the vector as addressable ! to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P ! for function parameters. */ ! c_common_mark_addressable_vec (*vecp); ! ! *vecp = build1 (VIEW_CONVERT_EXPR, ! build_array_type_nelts (TREE_TYPE (type), ! TYPE_VECTOR_SUBPARTS (type)), ! *vecp); } return ret; } Index: gcc/tree-ssa.c =================================================================== *** gcc/tree-ssa.c (revision 234545) --- gcc/tree-ssa.c (working copy) *************** non_rewritable_mem_ref_base (tree ref) *** 1284,1291 **** if (DECL_P (ref)) return NULL_TREE; ! while (handled_component_p (base)) ! base = TREE_OPERAND (base, 0); /* But watch out for MEM_REFs we cannot lower to a VIEW_CONVERT_EXPR or a BIT_FIELD_REF. */ --- 1284,1295 ---- if (DECL_P (ref)) return NULL_TREE; ! if (! strip_invariant_refs (base)) ! { ! base = get_base_address (base); ! if (DECL_P (base)) ! return base; ! } /* But watch out for MEM_REFs we cannot lower to a VIEW_CONVERT_EXPR or a BIT_FIELD_REF. */ Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 234545) --- gcc/gimple-fold.c (working copy) *************** maybe_canonicalize_mem_ref_addr (tree *t *** 3445,3450 **** --- 3445,3481 ---- if (TREE_CODE (*t) == ADDR_EXPR) t = &TREE_OPERAND (*t, 0); + /* The C and C++ frontends use an ARRAY_REF for indexing with their + generic vector extension. The actual vector referenced is + view-converted to an array type for this purpose. If the index + is constant the canonical representation in the middle-end is a + BIT_FIELD_REF so re-write the former to the latter here. */ + if (TREE_CODE (*t) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (*t, 0)) == VIEW_CONVERT_EXPR + && TREE_CODE (TREE_OPERAND (*t, 1)) == INTEGER_CST + && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0)))) + { + tree vtype = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*t, 0), 0)); + if (VECTOR_TYPE_P (vtype)) + { + tree low = array_ref_low_bound (*t); + if (TREE_CODE (low) == INTEGER_CST) + { + if (tree_int_cst_le (low, TREE_OPERAND (*t, 1))) + { + widest_int idx = wi::sub (wi::to_widest (TREE_OPERAND (*t, 1)), + wi::to_widest (low)); + if (wi::lts_p (idx, TYPE_VECTOR_SUBPARTS (vtype))) + *t = build3_loc (EXPR_LOCATION (*t), BIT_FIELD_REF, + TREE_TYPE (*t), + TREE_OPERAND (TREE_OPERAND (*t, 0), 0), + TYPE_SIZE (TREE_TYPE (vtype)), + wide_int_to_tree (sizetype, idx)); + } + } + } + } + while (handled_component_p (*t)) t = &TREE_OPERAND (*t, 0);