On Mon, 23 May 2016, Richard Biener wrote: > On Mon, 23 May 2016, Eric Botcazou wrote: > > > > The following changes the IL the C family frontends emit for > > > vector indexing from a mix of BIT_FIELD_REF (for constant indices) > > > and pointer arithmetic + dereferences (for variable indicies) to > > > a simple ARRAY_REF of the vector view-converted to a corresponding > > > array type. > > > > FWIW the Ada front-end (gigi) has always done that for its vector_type. > > Hmm, so it must have run into the bugfix part of this patch (the > tree-ssa.c hunk). And it will benefit from the gimple-fold.c hunk.
Marek noticed this fixes PR69504 as well. Added testcase and adjusted ChangeLog. Richard. 2016-05-23 Richard Biener <rguent...@suse.de> PR middle-end/70434 PR c/69504 c-family/ * c-common.c (convert_vector_to_pointer_for_subscript): Use a VIEW_CONVERT_EXPR to an array type. cp/ * expr.c (mark_exp_read): Handle VIEW_CONVERT_EXPR. * constexpr.c (cxx_eval_array_reference): Handle indexed vectors. c/ * c-typeck.c (build_array_ref): Do not complain about indexing non-lvalue vectors. * 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-20 13:55:56.047232610 +0200 --- gcc/c-family/c-common.c 2016-05-23 11:12:54.810910622 +0200 *************** convert_vector_to_pointer_for_subscript *** 12508,12561 **** 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; } --- 12508,12530 ---- 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-20 13:55:56.047232610 +0200 --- gcc/tree-ssa.c 2016-05-23 11:12:54.830910843 +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-20 13:55:56.047232610 +0200 --- gcc/cp/expr.c 2016-05-23 11:12:54.834910887 +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 10:18:16.902563063 +0200 --- gcc/c/c-typeck.c 2016-05-23 11:12:54.854911109 +0200 *************** build_array_ref (location_t loc, tree ar *** 2583,2588 **** --- 2583,2589 ---- gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); + bool was_vector = VECTOR_TYPE_P (TREE_TYPE (array)); bool non_lvalue = convert_vector_to_pointer_for_subscript (loc, &array, index); *************** 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) --- 2614,2621 ---- 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 10:18:19.602594260 +0200 --- gcc/cp/constexpr.c 2016-05-23 11:12:54.870911286 +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 10:18:20.550605213 +0200 --- gcc/gimple-fold.c 2016-05-23 11:12:54.878911374 +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 11:12:54.934911995 +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 11:18:28.850616190 +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]; + }