This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR70434, change FE IL for vector indexing


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.

This avoids making the vector address-taken and thus enables
better optimization in the middle-end.

Note the prefered middle-end IL for constant indices is still a
BIT_FIELD_REF but it's easy to restore there (and we have to do
that there anyway in case we propagate a constant into a previously
non-constant index).

For the testcase the middle-end now is able to remove the extra
temporary that was present before.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ok for trunk?

Thanks,
Richard.

2016-05-23  Richard Biener  <rguenther@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.

	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:26:45.515043467 +0200
--- gcc/c-family/c-common.c	2016-05-20 13:26:54.351145443 +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:26:45.519043514 +0200
--- gcc/tree-ssa.c	2016-05-20 13:26:54.351145443 +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:26:54.351145443 +0200
--- gcc/cp/expr.c	2016-05-20 13:34:41.788538563 +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-20 13:26:45.519043514 +0200
--- gcc/c/c-typeck.c	2016-05-20 13:26:54.355145488 +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-20 13:26:45.523043559 +0200
--- gcc/cp/constexpr.c	2016-05-20 13:26:54.355145488 +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-20 13:26:45.523043559 +0200
--- gcc/gimple-fold.c	2016-05-20 13:26:54.359145535 +0200
*************** maybe_canonicalize_mem_ref_addr (tree *t
*** 3441,3446 ****
--- 3441,3484 ----
    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-20 13:54:20.330129381 +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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]