[PATCH] Fix PR70434, change FE IL for vector indexing
Richard Biener
rguenther@suse.de
Mon May 23 14:23:00 GMT 2016
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 <rguenther@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)
{
More information about the Gcc-patches
mailing list