[PATCH] Move VEC_PERM_EXPR folding to match.pd

Richard Biener rguenther@suse.de
Mon May 20 08:52:00 GMT 2019


On Fri, 17 May 2019, Richard Biener wrote:

> 
> This moves things from fold-const.c to match.pd.

So there's an issue that was appearantly side-stepped in the GENERIC
folding by not re-folding the result.

        /* Generate a canonical form of the selector.  */
        if (sel.encoding () != builder)

"spuriously" returns true for some cases where we end up with
the same tree representation of the selector (I see
m_npatterns == 4 vs. 1 and m_nelts_per_pattern 1 vs. 3).

So I either have to double-check whether the re-created
op2 is really different from the original one or remove
those "premature" checks from vector_builder::operator==
where we then no longer can compare encoded elts...

Testing the variant with changed = operand_equal_p (...).

Richard.

> Bootstrap / regtest running on x86_64-unknown-linux-gnu.
> 
> Richard.
> 
> 2019-05-17  Richard Biener  <rguenther@suse.de>
> 
> 	* gimple-match-head.c: Include vec-perm-indices.h.
> 	* generic-match-head.c: Likewise.
> 	* fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h
> 	is included.
> 	* fold-const.c (fold_vec_perm): Export.
> 	(fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR...
> 	(match.pd): ...here.
> 
> Index: gcc/gimple-match-head.c
> ===================================================================
> --- gcc/gimple-match-head.c	(revision 271320)
> +++ gcc/gimple-match-head.c	(working copy)
> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.
>  #include "gimple.h"
>  #include "ssa.h"
>  #include "cgraph.h"
> +#include "vec-perm-indices.h"
>  #include "fold-const.h"
>  #include "fold-const-call.h"
>  #include "stor-layout.h"
> Index: gcc/generic-match-head.c
> ===================================================================
> --- gcc/generic-match-head.c	(revision 271320)
> +++ gcc/generic-match-head.c	(working copy)
> @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.
>  #include "gimple.h"
>  #include "ssa.h"
>  #include "cgraph.h"
> +#include "vec-perm-indices.h"
>  #include "fold-const.h"
>  #include "stor-layout.h"
>  #include "tree-dfa.h"
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c	(revision 271320)
> +++ gcc/fold-const.c	(working copy)
> @@ -9015,7 +9015,7 @@ vec_cst_ctor_to_array (tree arg, unsigne
>     selector.  Return the folded VECTOR_CST or CONSTRUCTOR if successful,
>     NULL_TREE otherwise.  */
>  
> -static tree
> +tree
>  fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel)
>  {
>    unsigned int i;
> @@ -11763,7 +11763,10 @@ fold_ternary_loc (location_t loc, enum t
>        return NULL_TREE;
>  
>      case VEC_PERM_EXPR:
> -      if (TREE_CODE (arg2) == VECTOR_CST)
> +      /* Perform constant folding of BIT_INSERT_EXPR.  */
> +      if (TREE_CODE (arg2) == VECTOR_CST
> +	  && TREE_CODE (op0) == VECTOR_CST
> +	  && TREE_CODE (op1) == VECTOR_CST)
>  	{
>  	  /* Build a vector of integers from the tree mask.  */
>  	  vec_perm_builder builder;
> @@ -11774,61 +11777,7 @@ fold_ternary_loc (location_t loc, enum t
>  	  poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
>  	  bool single_arg = (op0 == op1);
>  	  vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
> -
> -	  /* Check for cases that fold to OP0 or OP1 in their original
> -	     element order.  */
> -	  if (sel.series_p (0, 1, 0, 1))
> -	    return op0;
> -	  if (sel.series_p (0, 1, nelts, 1))
> -	    return op1;
> -
> -	  if (!single_arg)
> -	    {
> -	      if (sel.all_from_input_p (0))
> -		op1 = op0;
> -	      else if (sel.all_from_input_p (1))
> -		{
> -		  op0 = op1;
> -		  sel.rotate_inputs (1);
> -		}
> -	    }
> -
> -	  if ((TREE_CODE (op0) == VECTOR_CST
> -	       || TREE_CODE (op0) == CONSTRUCTOR)
> -	      && (TREE_CODE (op1) == VECTOR_CST
> -		  || TREE_CODE (op1) == CONSTRUCTOR))
> -	    {
> -	      tree t = fold_vec_perm (type, op0, op1, sel);
> -	      if (t != NULL_TREE)
> -		return t;
> -	    }
> -
> -	  bool changed = (op0 == op1 && !single_arg);
> -
> -	  /* Generate a canonical form of the selector.  */
> -	  if (arg2 == op2 && sel.encoding () != builder)
> -	    {
> -	      /* Some targets are deficient and fail to expand a single
> -		 argument permutation while still allowing an equivalent
> -		 2-argument version.  */
> -	      if (sel.ninputs () == 2
> -		  || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
> -		op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
> -	      else
> -		{
> -		  vec_perm_indices sel2 (builder, 2, nelts);
> -		  if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
> -		    op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel2);
> -		  else
> -		    /* Not directly supported with either encoding,
> -		       so use the preferred form.  */
> -		    op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
> -		}
> -	      changed = true;
> -	    }
> -
> -	  if (changed)
> -	    return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2);
> +	  return fold_vec_perm (type, op0, op1, sel);
>  	}
>        return NULL_TREE;
>  
> Index: gcc/fold-const.h
> ===================================================================
> --- gcc/fold-const.h	(revision 271320)
> +++ gcc/fold-const.h	(working copy)
> @@ -100,6 +100,9 @@ extern tree fold_bit_and_mask (tree, tre
>  			       tree, enum tree_code, tree, tree,
>  			       tree, enum tree_code, tree, tree, tree *);
>  extern tree fold_read_from_constant_string (tree);
> +#if GCC_VEC_PERN_INDICES_H
> +extern tree fold_vec_perm (tree, tree, tree, const vec_perm_indices &);
> +#endif
>  extern bool wide_int_binop (wide_int &res, enum tree_code,
>  			    const wide_int &arg1, const wide_int &arg2,
>  			    signop, wi::overflow_type *);
> Index: gcc/match.pd
> ===================================================================
> --- gcc/match.pd	(revision 271320)
> +++ gcc/match.pd	(working copy)
> @@ -5374,3 +5374,83 @@ (define_operator_list COND_TERNARY
>        (bit_and:elt_type
>         (BIT_FIELD_REF:elt_type @0 { size; } { pos; })
>         { elt; })))))))
> +
> +(simplify
> + (vec_perm @0 @1 VECTOR_CST@2)
> + (with
> +  {
> +    tree op0 = @0, op1 = @1, op2 = @2;
> +
> +    /* Build a vector of integers from the tree mask.  */
> +    vec_perm_builder builder;
> +    if (!tree_to_vec_perm_builder (&builder, op2))
> +      return NULL_TREE;
> +
> +    /* Create a vec_perm_indices for the integer vector.  */
> +    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
> +    bool single_arg = (op0 == op1);
> +    vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
> +  }
> +  (if (sel.series_p (0, 1, 0, 1))
> +   { op0; }
> +   (if (sel.series_p (0, 1, nelts, 1))
> +    { op1; }
> +    (with
> +     {
> +       if (!single_arg)
> +         {
> +	   if (sel.all_from_input_p (0))
> +	     op1 = op0;
> +	   else if (sel.all_from_input_p (1))
> +	     {
> +	       op0 = op1;
> +	       sel.rotate_inputs (1);
> +	     }
> +         }
> +       gassign *def;
> +       tree cop0 = op0, cop1 = op1;
> +       if (TREE_CODE (op0) == SSA_NAME
> +           && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0)))
> +	   && gimple_assign_rhs_code (def) == CONSTRUCTOR)
> +	 cop0 = gimple_assign_rhs1 (def);
> +       if (TREE_CODE (op1) == SSA_NAME
> +           && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op1)))
> +	   && gimple_assign_rhs_code (def) == CONSTRUCTOR)
> +	 cop1 = gimple_assign_rhs1 (def);
> +
> +       tree t;
> +    }
> +    (if ((TREE_CODE (cop0) == VECTOR_CST
> +	  || TREE_CODE (cop0) == CONSTRUCTOR)
> +	 && (TREE_CODE (cop1) == VECTOR_CST
> +	     || TREE_CODE (cop1) == CONSTRUCTOR)
> +	 && (t = fold_vec_perm (type, cop0, cop1, sel)))
> +     { t; }
> +     (with
> +      {
> +	bool changed = (op0 == op1 && !single_arg);
> +
> +	/* Generate a canonical form of the selector.  */
> +	if (sel.encoding () != builder)
> +	  {
> +	    /* Some targets are deficient and fail to expand a single
> +	       argument permutation while still allowing an equivalent
> +	       2-argument version.  */
> +	    if (sel.ninputs () == 2
> +	       || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
> +	      op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
> +	    else
> +	      {
> +	        vec_perm_indices sel2 (builder, 2, nelts);
> +	        if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
> +	          op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel2);
> +	        else
> +	          /* Not directly supported with either encoding,
> +		     so use the preferred form.  */
> +		  op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
> +	      }
> +	    changed = true;
> +	  }
> +      }
> +      (if (changed)
> +       (vec_perm { op0; } { op1; } { op2; })))))))))
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG NÌrnberg)


More information about the Gcc-patches mailing list