On Mon, 23 May 2016, Jason Merrill wrote: > On 05/23/2016 05:19 AM, Richard Biener wrote: > > * c-common.c (convert_vector_to_pointer_for_subscript): Use a > > VIEW_CONVERT_EXPR to an array type. > > Since we aren't converting to pointer type anymore, the function name should > probably change, or at least the comment. > > OK with that adjustment.
Good point - I've renamed it to convert_vector_to_array_for_subscript, see below. Richard. 2016-05-23 Richard Biener <rguent...@suse.de> PR middle-end/70434 PR c/69504 c-family/ * c-common.h (convert_vector_to_pointer_for_subscript): Rename to ... (convert_vector_to_array_for_subscript): ... this. * c-common.c (convert_vector_to_pointer_for_subscript): Use a VIEW_CONVERT_EXPR to an array type. Rename to ... (convert_vector_to_array_for_subscript): ... this. cp/ * expr.c (mark_exp_read): Handle VIEW_CONVERT_EXPR. * constexpr.c (cxx_eval_array_reference): Handle indexed vectors. * typeck.c (cp_build_array_ref): Adjust. c/ * c-typeck.c (build_array_ref): Do not complain about indexing non-lvalue vectors. Adjust for function name change. * 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. * c-c++-common/vector-subscript-4.c: New testcase. Index: gcc/c-family/c-common.c =================================================================== *** gcc/c-family/c-common.c.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/c-family/c-common.c 2016-05-23 16:18:47.888831760 +0200 *************** build_userdef_literal (tree suffix_id, t *** 12496,12561 **** return literal; } ! /* For vector[index], convert the vector to a ! pointer of the underlying type. Return true if the resulting ! ARRAY_REF should not be an lvalue. */ bool ! convert_vector_to_pointer_for_subscript (location_t loc, ! tree *vecp, tree index) { bool ret = false; 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; } --- 12496,12529 ---- return literal; } ! /* For vector[index], convert the vector to an array of the underlying type. ! Return true if the resulting ARRAY_REF should not be an lvalue. */ bool ! convert_vector_to_array_for_subscript (location_t loc, ! tree *vecp, tree index) { bool ret = false; 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.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/tree-ssa.c 2016-05-23 16:17:40.944040654 +0200 *************** maybe_rewrite_mem_ref_base (tree *tp, bi *** 1250,1263 **** static tree non_rewritable_mem_ref_base (tree ref) { ! tree base = ref; /* A plain decl does not need it set. */ 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. */ --- 1250,1268 ---- static tree non_rewritable_mem_ref_base (tree ref) { ! tree base; /* A plain decl does not need it set. */ if (DECL_P (ref)) return NULL_TREE; ! if (! (base = CONST_CAST_TREE (strip_invariant_refs (ref)))) ! { ! base = get_base_address (ref); ! if (DECL_P (base)) ! return base; ! return NULL_TREE; ! } /* But watch out for MEM_REFs we cannot lower to a VIEW_CONVERT_EXPR or a BIT_FIELD_REF. */ Index: gcc/cp/expr.c =================================================================== *** gcc/cp/expr.c.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/cp/expr.c 2016-05-23 16:17:41.028041649 +0200 *************** mark_exp_read (tree exp) *** 146,151 **** --- 146,152 ---- case INDIRECT_REF: case FLOAT_EXPR: case NON_DEPENDENT_EXPR: + case VIEW_CONVERT_EXPR: mark_exp_read (TREE_OPERAND (exp, 0)); break; case COMPOUND_EXPR: Index: gcc/c/c-typeck.c =================================================================== *** gcc/c/c-typeck.c.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/c/c-typeck.c 2016-05-23 16:19:31.661348906 +0200 *************** build_array_ref (location_t loc, tree ar *** 2583,2590 **** gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); ! bool non_lvalue ! = convert_vector_to_pointer_for_subscript (loc, &array, index); if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { --- 2583,2590 ---- gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); ! bool was_vector = VECTOR_TYPE_P (TREE_TYPE (array)); ! bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, index); if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { *************** build_array_ref (location_t loc, tree ar *** 2613,2619 **** return error_mark_node; } ! if (pedantic || warn_c90_c99_compat) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) --- 2613,2620 ---- return error_mark_node; } ! if ((pedantic || warn_c90_c99_compat) ! && ! was_vector) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) Index: gcc/cp/constexpr.c =================================================================== *** gcc/cp/constexpr.c.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/cp/constexpr.c 2016-05-23 16:17:41.104042546 +0200 *************** cxx_eval_array_reference (const constexp *** 1977,1982 **** --- 1977,1986 ---- else if (lval) return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL); elem_type = TREE_TYPE (TREE_TYPE (ary)); + if (TREE_CODE (ary) == VIEW_CONVERT_EXPR + && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0))) + && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0)))) + ary = TREE_OPERAND (ary, 0); if (TREE_CODE (ary) == CONSTRUCTOR) len = CONSTRUCTOR_NELTS (ary); else if (TREE_CODE (ary) == STRING_CST) *************** cxx_eval_array_reference (const constexp *** 1985,1990 **** --- 1989,1996 ---- / TYPE_PRECISION (char_type_node)); len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars; } + else if (TREE_CODE (ary) == VECTOR_CST) + len = VECTOR_CST_NELTS (ary); else { /* We can't do anything with other tree codes, so use *************** cxx_eval_array_reference (const constexp *** 2001,2007 **** return t; } ! tree nelts = array_type_nelts_top (TREE_TYPE (ary)); /* For VLAs, the number of elements won't be an integer constant. */ nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p); --- 2007,2020 ---- return t; } ! tree nelts; ! if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) ! nelts = array_type_nelts_top (TREE_TYPE (ary)); ! else if (VECTOR_TYPE_P (TREE_TYPE (ary))) ! nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); ! else ! gcc_unreachable (); ! /* For VLAs, the number of elements won't be an integer constant. */ nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p); *************** cxx_eval_array_reference (const constexp *** 2047,2052 **** --- 2060,2067 ---- if (TREE_CODE (ary) == CONSTRUCTOR) return (*CONSTRUCTOR_ELTS (ary))[i].value; + else if (TREE_CODE (ary) == VECTOR_CST) + return VECTOR_CST_ELT (ary, i); else if (elem_nchars == 1) return build_int_cst (cv_unqualified (TREE_TYPE (TREE_TYPE (ary))), TREE_STRING_POINTER (ary)[i]); Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c.orig 2016-05-23 11:18:50.966861914 +0200 --- gcc/gimple-fold.c 2016-05-23 16:17:41.104042546 +0200 *************** maybe_canonicalize_mem_ref_addr (tree *t *** 3456,3461 **** --- 3456,3499 ---- 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)); + idx = wi::mul (idx, wi::to_widest + (TYPE_SIZE (TREE_TYPE (*t)))); + widest_int ext + = wi::add (idx, wi::to_widest (TYPE_SIZE (TREE_TYPE (*t)))); + if (wi::les_p (ext, wi::to_widest (TYPE_SIZE (vtype)))) + { + *t = build3_loc (EXPR_LOCATION (*t), BIT_FIELD_REF, + TREE_TYPE (*t), + TREE_OPERAND (TREE_OPERAND (*t, 0), 0), + TYPE_SIZE (TREE_TYPE (*t)), + wide_int_to_tree (sizetype, idx)); + res = true; + } + } + } + } + } + while (handled_component_p (*t)) t = &TREE_OPERAND (*t, 0); Index: gcc/testsuite/c-c++-common/vector-subscript-4.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/c-c++-common/vector-subscript-4.c 2016-05-23 16:17:41.148043066 +0200 *************** *** 0 **** --- 1,29 ---- + /* { dg-do compile } */ + /* { dg-options "-O2 -fdump-tree-optimized -w -Wno-psabi" } */ + + #define foobar(n) \ + typedef int v##n##si __attribute__ ((vector_size (4 * n))); \ + \ + int \ + foo##n(int x, v##n##si v) \ + { \ + v[0] ^= v[1]; \ + return ((v##n##si)v)[x]; \ + } \ + \ + int \ + bar##n(int x, v##n##si v) \ + { \ + v[0] ^= v[1]; \ + return v[x]; \ + } + + foobar(2) + foobar(4) + foobar(8) + foobar(16) + foobar(32) + foobar(64) + + /* Verify we don't have any vector temporaries in the IL. */ + /* { dg-final { scan-tree-dump-not "vector" "optimized" } } */ Index: gcc/testsuite/c-c++-common/vector-subscript-5.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/c-c++-common/vector-subscript-5.c 2016-05-23 16:17:41.148043066 +0200 *************** *** 0 **** --- 1,13 ---- + /* { dg-do compile } */ + + typedef int U __attribute__ ((vector_size (16))); + + int + foo (int i) + { + register U u + #if __SSE2__ + asm ("xmm0"); + #endif + return u[i]; + } Index: gcc/c-family/c-common.h =================================================================== *** gcc/c-family/c-common.h.orig 2016-05-12 09:20:08.812500849 +0200 --- gcc/c-family/c-common.h 2016-05-23 16:19:05.813043536 +0200 *************** extern tree build_userdef_literal (tree *** 1368,1374 **** enum overflow_type overflow, tree num_string); ! extern bool convert_vector_to_pointer_for_subscript (location_t, tree *, tree); /* Possibe cases of scalar_to_vector conversion. */ enum stv_conv { --- 1368,1374 ---- enum overflow_type overflow, tree num_string); ! extern bool convert_vector_to_array_for_subscript (location_t, tree *, tree); /* Possibe cases of scalar_to_vector conversion. */ enum stv_conv { Index: gcc/cp/typeck.c =================================================================== *** gcc/cp/typeck.c.orig 2016-05-17 09:50:48.600900884 +0200 --- gcc/cp/typeck.c 2016-05-23 16:19:49.681561776 +0200 *************** cp_build_array_ref (location_t loc, tree *** 3161,3168 **** break; } ! bool non_lvalue ! = convert_vector_to_pointer_for_subscript (loc, &array, idx); if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { --- 3161,3167 ---- break; } ! bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, idx); if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) {