From f17a223de829cb5fa0b32a9f12c22a4fa929506c Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 24 May 2016 07:55:56 +0000 Subject: [PATCH] re PR middle-end/70434 (adding an extraneous cast to vector type results in inferior code) 2016-05-24 Richard Biener 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. * c-c++-common/vector-subscript-5.c: Likewise. From-SVN: r236630 --- gcc/ChangeLog | 9 +++ gcc/c-family/ChangeLog | 10 ++++ gcc/c-family/c-common.c | 60 +++++-------------- gcc/c-family/c-common.h | 2 +- gcc/c/ChangeLog | 7 +++ gcc/c/c-typeck.c | 7 ++- gcc/cp/ChangeLog | 9 +++ gcc/cp/constexpr.c | 17 +++++- gcc/cp/expr.c | 1 + gcc/cp/typeck.c | 3 +- gcc/gimple-fold.c | 38 ++++++++++++ gcc/testsuite/ChangeLog | 7 +++ .../c-c++-common/vector-subscript-4.c | 29 +++++++++ .../c-c++-common/vector-subscript-5.c | 13 ++++ gcc/tree-ssa.c | 11 +++- 15 files changed, 167 insertions(+), 56 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/vector-subscript-4.c create mode 100644 gcc/testsuite/c-c++-common/vector-subscript-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d4d12b14052..d94460e9419 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-05-24 Richard Biener + + PR middle-end/70434 + PR c/69504 + * 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. + 2016-05-24 Kugan Vivekanandarajah PR middle-end/71170 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index f6ba9410200..7f0ca2d8057 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,13 @@ +2016-05-24 Richard Biener + + PR middle-end/70434 + PR c/69504 + * 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. + 2016-05-12 Marek Polacek PR c/70756 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 146e8059c1a..4568cf62a98 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -12496,66 +12496,34 @@ build_userdef_literal (tree suffix_id, tree value, 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. */ +/* 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_pointer_for_subscript (location_t loc, - tree *vecp, tree index) +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); - 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); + /* 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; } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 0ee9f567123..0295532d3ea 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1368,7 +1368,7 @@ extern tree build_userdef_literal (tree suffix_id, tree value, enum overflow_type overflow, tree num_string); -extern bool convert_vector_to_pointer_for_subscript (location_t, tree *, tree); +extern bool convert_vector_to_array_for_subscript (location_t, tree *, tree); /* Possibe cases of scalar_to_vector conversion. */ enum stv_conv { diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index c65f2e9e5e0..9bb5ec1dfce 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2016-05-24 Richard Biener + + PR middle-end/70434 + PR c/69504 + * c-typeck.c (build_array_ref): Do not complain about indexing + non-lvalue vectors. Adjust for function name change. + 2016-05-20 Martin Sebor PR c/71115 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 7c9b078ed1b..74bad2acc5d 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2583,8 +2583,8 @@ build_array_ref (location_t loc, tree array, tree index) gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); - bool non_lvalue - = convert_vector_to_pointer_for_subscript (loc, &array, index); + 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) { @@ -2613,7 +2613,8 @@ build_array_ref (location_t loc, tree array, tree index) return error_mark_node; } - if (pedantic || warn_c90_c99_compat) + if ((pedantic || warn_c90_c99_compat) + && ! was_vector) { tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9095576dd4a..eaf42b83f1c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2016-05-24 Richard Biener + + PR middle-end/70434 + PR c/69504 + * 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. + 2016-05-23 Jason Merrill PR c++/70344 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index bb723f45b09..482f8afaeb6 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1983,6 +1983,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, 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) @@ -1991,6 +1995,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, / 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 @@ -2007,7 +2013,14 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, return t; } - tree nelts = array_type_nelts_top (TREE_TYPE (ary)); + 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); @@ -2053,6 +2066,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, 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]); diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c index 61b395300e6..e879f3c5e8d 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -146,6 +146,7 @@ mark_exp_read (tree exp) 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: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index cd058fa258e..8b3fec66250 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3161,8 +3161,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx, break; } - bool non_lvalue - = convert_vector_to_pointer_for_subscript (loc, &array, idx); + bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, idx); if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 858f4844426..83b71509988 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3459,6 +3459,44 @@ maybe_canonicalize_mem_ref_addr (tree *t) 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 32e95227be2..65589fa4eff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-05-24 Richard Biener + + PR middle-end/70434 + PR c/69504 + * c-c++-common/vector-subscript-4.c: New testcase. + * c-c++-common/vector-subscript-5.c: Likewise. + 2016-05-23 Jerry DeLisle PR fortran/71123 diff --git a/gcc/testsuite/c-c++-common/vector-subscript-4.c b/gcc/testsuite/c-c++-common/vector-subscript-4.c new file mode 100644 index 00000000000..2c2481f88b7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/vector-subscript-4.c @@ -0,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" } } */ diff --git a/gcc/testsuite/c-c++-common/vector-subscript-5.c b/gcc/testsuite/c-c++-common/vector-subscript-5.c new file mode 100644 index 00000000000..58a94f0fb15 --- /dev/null +++ b/gcc/testsuite/c-c++-common/vector-subscript-5.c @@ -0,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]; +} diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index cf6e76405b3..a53322d9837 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1222,14 +1222,19 @@ maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming) static tree non_rewritable_mem_ref_base (tree ref) { - tree base = ref; + tree base; /* 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); + 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. */ -- 2.30.2