On Fri, May 3, 2019 at 6:02 AM Richard Biener <rguent...@suse.de> wrote:
>
>
> The following refactors simplify_vector_constructor and adds
> handling of constants to it in a straight-forward way.
>
> A followup will handle the testcases posted in HJs patch.
>
> Bootstrap / regtest running on x86_64-unknown-linux-gnu.
>
> Richard.
>
> 2019-05-03  Richard Biener  <rguent...@suse.de>
>
>         PR tree-optimization/88828
>         * tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from...
>         (simplify_vector_constructor): ...here.  Handle constants in
>         the constructor.
>
>         * gcc.target/i386/pr88828-0.c: New testcase.
>
> Index: gcc/tree-ssa-forwprop.c
> ===================================================================
> --- gcc/tree-ssa-forwprop.c     (revision 270847)
> +++ gcc/tree-ssa-forwprop.c     (working copy)
> @@ -1997,6 +1997,44 @@ simplify_permutation (gimple_stmt_iterat
>    return 0;
>  }
>
> +/* Get the BIT_FIELD_REF definition of VAL, if any, looking through
> +   conversions with code CONV_CODE or update it if still ERROR_MARK.
> +   Return NULL_TREE if no such matching def was found.  */
> +
> +static tree
> +get_bit_field_ref_def (tree val, enum tree_code &conv_code)
> +{
> +  if (TREE_CODE (val) != SSA_NAME)
> +    return NULL_TREE ;
> +  gimple *def_stmt = get_prop_source_stmt (val, false, NULL);
> +  if (!def_stmt)
> +    return NULL_TREE;
> +  enum tree_code code = gimple_assign_rhs_code (def_stmt);
> +  if (code == FLOAT_EXPR
> +      || code == FIX_TRUNC_EXPR)
> +    {
> +      tree op1 = gimple_assign_rhs1 (def_stmt);
> +      if (conv_code == ERROR_MARK)
> +       {
> +         if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))),
> +                       GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
> +           return NULL_TREE;
> +         conv_code = code;
> +       }
> +      else if (conv_code != code)
> +       return NULL_TREE;
> +      if (TREE_CODE (op1) != SSA_NAME)
> +       return NULL_TREE;
> +      def_stmt = SSA_NAME_DEF_STMT (op1);
> +      if (! is_gimple_assign (def_stmt))
> +       return NULL_TREE;
> +      code = gimple_assign_rhs_code (def_stmt);
> +    }
> +  if (code != BIT_FIELD_REF)
> +    return NULL_TREE;
> +  return gimple_assign_rhs1 (def_stmt);
> +}
> +
>  /* Recognize a VEC_PERM_EXPR.  Returns true if there were any changes.  */
>
>  static bool
> @@ -2027,6 +2065,9 @@ simplify_vector_constructor (gimple_stmt
>    orig[1] = NULL;
>    conv_code = ERROR_MARK;
>    maybe_ident = true;
> +  tree one_constant = NULL_TREE;
> +  auto_vec<tree> constants;
> +  constants.safe_grow_cleared (nelts);
>    FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
>      {
>        tree ref, op1;
> @@ -2034,68 +2075,55 @@ simplify_vector_constructor (gimple_stmt
>        if (i >= nelts)
>         return false;
>
> -      if (TREE_CODE (elt->value) != SSA_NAME)
> -       return false;
> -      def_stmt = get_prop_source_stmt (elt->value, false, NULL);
> -      if (!def_stmt)
> -       return false;
> -      code = gimple_assign_rhs_code (def_stmt);
> -      if (code == FLOAT_EXPR
> -         || code == FIX_TRUNC_EXPR)
> +      op1 = get_bit_field_ref_def (elt->value, conv_code);
> +      if (op1)
>         {
> -         op1 = gimple_assign_rhs1 (def_stmt);
> -         if (conv_code == ERROR_MARK)
> +         ref = TREE_OPERAND (op1, 0);
> +         unsigned int j;
> +         for (j = 0; j < 2; ++j)
>             {
> -             if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE 
> (elt->value))),
> -                           GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
> -               return false;
> -             conv_code = code;
> +             if (!orig[j])
> +               {
> +                 if (TREE_CODE (ref) != SSA_NAME)
> +                   return false;
> +                 if (! VECTOR_TYPE_P (TREE_TYPE (ref))
> +                     || ! useless_type_conversion_p (TREE_TYPE (op1),
> +                                                     TREE_TYPE (TREE_TYPE 
> (ref))))
> +                   return false;
> +                 if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
> +                                                      TREE_TYPE (ref)))
> +                   return false;
> +                 orig[j] = ref;
> +                 break;
> +               }
> +             else if (ref == orig[j])
> +               break;
>             }
> -         else if (conv_code != code)
> +         if (j == 2)
>             return false;
> -         if (TREE_CODE (op1) != SSA_NAME)
> -           return false;
> -         def_stmt = SSA_NAME_DEF_STMT (op1);
> -         if (! is_gimple_assign (def_stmt))
> +
> +         unsigned int elt;
> +         if (maybe_ne (bit_field_size (op1), elem_size)
> +             || !constant_multiple_p (bit_field_offset (op1), elem_size, 
> &elt))
>             return false;
> -         code = gimple_assign_rhs_code (def_stmt);
> +         if (j)
> +           elt += nelts;
> +         if (elt != i)
> +           maybe_ident = false;
> +         sel.quick_push (elt);
>         }
> -      if (code != BIT_FIELD_REF)
> -       return false;
> -      op1 = gimple_assign_rhs1 (def_stmt);
> -      ref = TREE_OPERAND (op1, 0);
> -      unsigned int j;
> -      for (j = 0; j < 2; ++j)
> +      else if (CONSTANT_CLASS_P (elt->value))
>         {
> -         if (!orig[j])
> -           {
> -             if (TREE_CODE (ref) != SSA_NAME)
> -               return false;
> -             if (! VECTOR_TYPE_P (TREE_TYPE (ref))
> -                 || ! useless_type_conversion_p (TREE_TYPE (op1),
> -                                                 TREE_TYPE (TREE_TYPE 
> (ref))))
> -               return false;
> -             if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
> -                                                  TREE_TYPE (ref)))
> -               return false;
> -             orig[j] = ref;
> -             break;
> -           }
> -         else if (ref == orig[j])
> -           break;

Missing else
                 return false;

[hjl@gnu-cfl-1 pr88828]$ cat x5.i
typedef float __v4sf __attribute__ ((__vector_size__ (16)));

__v4sf
foo (__v4sf x, float f, float z)
{
  __v4sf y =  { f, x[0], z, x[3] };
  return y;
}
[hjl@gnu-cfl-1 pr88828]$ make x5.s
/export/build/gnu/tools-build/gcc-wip-debug/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/tools-build/gcc-wip-debug/build-x86_64-linux/gcc/
-O2  -S x5.i
during GIMPLE pass: forwprop
x5.i: In function ‘foo’:
x5.i:8:1: internal compiler error: in elt, at vector-builder.h:202
    8 | }
      | ^
0xe3fb73 vector_builder<poly_int<1u, long>,
int_vector_builder<poly_int<1u, long> > >::elt(unsigned int) const
/export/gnu/import/git/gitlab/x86-gcc/gcc/vector-builder.h:202
0x17b5665 vec_perm_indices::new_vector(int_vector_builder<poly_int<1u,
long> > const&, unsigned int, poly_int<1u, unsigned long>)
/export/gnu/import/git/gitlab/x86-gcc/gcc/vec-perm-indices.c:65
0xe3f93b vec_perm_indices::vec_perm_indices(int_vector_builder<poly_int<1u,
long> > const&, unsigned int, poly_int<1u, unsigned long>)
/export/gnu/import/git/gitlab/x86-gcc/gcc/vec-perm-indices.h:112
0x14e5fef simplify_vector_constructor
/export/gnu/import/git/gitlab/x86-gcc/gcc/tree-ssa-forwprop.c:2155
0x14e8676 execute
/export/gnu/import/git/gitlab/x86-gcc/gcc/tree-ssa-forwprop.c:2693
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.
make: *** [Makefile:19: x5.s] Error 1
[hjl@gnu-cfl-1 pr88828]$

This comes from my PR 88828 tests.

> +         if (orig[1]
> +             && orig[1] != error_mark_node)
> +           return false;
> +         orig[1] = error_mark_node;
> +         if (!one_constant)
> +           one_constant = elt->value;
> +         constants[i] = elt->value;
> +         sel.quick_push (i + nelts);
> +         maybe_ident = false;
>         }
> -      if (j == 2)
> -       return false;
> -
> -      unsigned int elt;
> -      if (maybe_ne (bit_field_size (op1), elem_size)
> -         || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
> -       return false;
> -      if (j)
> -       elt += nelts;
> -      if (elt != i)
> -       maybe_ident = false;
> -      sel.quick_push (elt);
>      }
>    if (i < nelts)
>      return false;
> @@ -2138,9 +2166,29 @@ simplify_vector_constructor (gimple_stmt
>        op2 = vec_perm_indices_to_tree (mask_type, indices);
>        if (!orig[1])
>         orig[1] = orig[0];
> +      if (orig[1] == error_mark_node)
> +       {
> +         tree_vector_builder vec (type, nelts, 1);
> +         for (unsigned i = 0; i < nelts; ++i)
> +           if (constants[i])
> +             vec.quick_push (constants[i]);
> +           else
> +             /* ??? Push a don't-care value.  */
> +             vec.quick_push (one_constant);
> +         orig[1] = vec.build ();
> +       }
>        if (conv_code == ERROR_MARK)
>         gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
>                                         orig[1], op2);
> +      else if (TREE_CODE (orig[1]) == VECTOR_CST)
> +       {
> +         gimple *conv
> +           = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);
> +         orig[0] = gimple_assign_lhs (conv);
> +         gsi_insert_before (gsi, conv, GSI_SAME_STMT);
> +         gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR,
> +                                         orig[0], orig[1], op2);
> +       }
>        else
>         {
>           gimple *perm

Here is the updated patch.

-- 
H.J.
From 3d306956a4de03cf725448101ba5d4bd438cd441 Mon Sep 17 00:00:00 2001
From: Richard Biener <rguent...@suse.de>
Date: Fri, 3 May 2019 08:22:12 -0700
Subject: [PATCH] Prep for PR88828 fix

The following refactors simplify_vector_constructor and adds
handling of constants to it in a straight-forward way.

A followup will handle the testcases posted in HJs patch.

Bootstrap / regtest running on x86_64-unknown-linux-gnu.

2019-05-03  Richard Biener  <rguent...@suse.de>

	PR tree-optimization/88828
	* tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from...
	(simplify_vector_constructor): ...here.  Handle constants in
	the constructor.

	* gcc.target/i386/pr88828-0.c: New testcase.
---
 gcc/testsuite/gcc.target/i386/pr88828-0.c |  27 ++++
 gcc/tree-ssa-forwprop.c                   | 159 ++++++++++++++--------
 2 files changed, 131 insertions(+), 55 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr88828-0.c

diff --git a/gcc/testsuite/gcc.target/i386/pr88828-0.c b/gcc/testsuite/gcc.target/i386/pr88828-0.c
new file mode 100644
index 00000000000..3ddb2d13526
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-0.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse4.2" } */
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef float v4sf __attribute__((vector_size(16)));
+
+v4si foo (v4si x)
+{
+  return (v4si){ x[0], 1, x[2], 3 };
+}
+
+/* { dg-final { scan-assembler "pblendw" } } */
+
+v4si bar (v4sf x)
+{
+  return (v4si){ 1, x[1], x[2], 3 };
+}
+
+/* { dg-final { scan-assembler "cvttps2dq" } } */
+/* { dg-final { scan-assembler "pblendw" } } */
+
+v4si baz (v4si x)
+{
+  return (v4si) { x[1], x[2], x[3], 0 };
+}
+
+/* { dg-final { scan-assembler "psrldq" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 1553c9e70ac..7dd1e64335a 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1997,17 +1997,54 @@ simplify_permutation (gimple_stmt_iterator *gsi)
   return 0;
 }
 
+/* Get the BIT_FIELD_REF definition of VAL, if any, looking through
+   conversions with code CONV_CODE or update it if still ERROR_MARK.
+   Return NULL_TREE if no such matching def was found.  */
+
+static tree
+get_bit_field_ref_def (tree val, enum tree_code &conv_code)
+{
+  if (TREE_CODE (val) != SSA_NAME)
+    return NULL_TREE ;
+  gimple *def_stmt = get_prop_source_stmt (val, false, NULL);
+  if (!def_stmt)
+    return NULL_TREE;
+  enum tree_code code = gimple_assign_rhs_code (def_stmt);
+  if (code == FLOAT_EXPR
+      || code == FIX_TRUNC_EXPR)
+    {
+      tree op1 = gimple_assign_rhs1 (def_stmt);
+      if (conv_code == ERROR_MARK)
+	{
+	  if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))),
+			GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
+	    return NULL_TREE;
+	  conv_code = code;
+	}
+      else if (conv_code != code)
+	return NULL_TREE;
+      if (TREE_CODE (op1) != SSA_NAME)
+	return NULL_TREE;
+      def_stmt = SSA_NAME_DEF_STMT (op1);
+      if (! is_gimple_assign (def_stmt))
+	return NULL_TREE;
+      code = gimple_assign_rhs_code (def_stmt);
+    }
+  if (code != BIT_FIELD_REF)
+    return NULL_TREE;
+  return gimple_assign_rhs1 (def_stmt);
+}
+
 /* Recognize a VEC_PERM_EXPR.  Returns true if there were any changes.  */
 
 static bool
 simplify_vector_constructor (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
-  gimple *def_stmt;
   tree op, op2, orig[2], type, elem_type;
   unsigned elem_size, i;
   unsigned HOST_WIDE_INT nelts;
-  enum tree_code code, conv_code;
+  enum tree_code conv_code;
   constructor_elt *elt;
   bool maybe_ident;
 
@@ -2027,6 +2064,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   orig[1] = NULL;
   conv_code = ERROR_MARK;
   maybe_ident = true;
+  tree one_constant = NULL_TREE;
+  auto_vec<tree> constants;
+  constants.safe_grow_cleared (nelts);
   FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
     {
       tree ref, op1;
@@ -2034,68 +2074,57 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       if (i >= nelts)
 	return false;
 
-      if (TREE_CODE (elt->value) != SSA_NAME)
-	return false;
-      def_stmt = get_prop_source_stmt (elt->value, false, NULL);
-      if (!def_stmt)
-	return false;
-      code = gimple_assign_rhs_code (def_stmt);
-      if (code == FLOAT_EXPR
-	  || code == FIX_TRUNC_EXPR)
+      op1 = get_bit_field_ref_def (elt->value, conv_code);
+      if (op1)
 	{
-	  op1 = gimple_assign_rhs1 (def_stmt);
-	  if (conv_code == ERROR_MARK)
+	  ref = TREE_OPERAND (op1, 0);
+	  unsigned int j;
+	  for (j = 0; j < 2; ++j)
 	    {
-	      if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (elt->value))),
-			    GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
-		return false;
-	      conv_code = code;
+	      if (!orig[j])
+		{
+		  if (TREE_CODE (ref) != SSA_NAME)
+		    return false;
+		  if (! VECTOR_TYPE_P (TREE_TYPE (ref))
+		      || ! useless_type_conversion_p (TREE_TYPE (op1),
+						      TREE_TYPE (TREE_TYPE (ref))))
+		    return false;
+		  if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
+						       TREE_TYPE (ref)))
+		    return false;
+		  orig[j] = ref;
+		  break;
+		}
+	      else if (ref == orig[j])
+		break;
 	    }
-	  else if (conv_code != code)
-	    return false;
-	  if (TREE_CODE (op1) != SSA_NAME)
+	  if (j == 2)
 	    return false;
-	  def_stmt = SSA_NAME_DEF_STMT (op1);
-	  if (! is_gimple_assign (def_stmt))
+
+	  unsigned int elt;
+	  if (maybe_ne (bit_field_size (op1), elem_size)
+	      || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
 	    return false;
-	  code = gimple_assign_rhs_code (def_stmt);
+	  if (j)
+	    elt += nelts;
+	  if (elt != i)
+	    maybe_ident = false;
+	  sel.quick_push (elt);
 	}
-      if (code != BIT_FIELD_REF)
-	return false;
-      op1 = gimple_assign_rhs1 (def_stmt);
-      ref = TREE_OPERAND (op1, 0);
-      unsigned int j;
-      for (j = 0; j < 2; ++j)
+      else if (CONSTANT_CLASS_P (elt->value))
 	{
-	  if (!orig[j])
-	    {
-	      if (TREE_CODE (ref) != SSA_NAME)
-		return false;
-	      if (! VECTOR_TYPE_P (TREE_TYPE (ref))
-		  || ! useless_type_conversion_p (TREE_TYPE (op1),
-						  TREE_TYPE (TREE_TYPE (ref))))
-		return false;
-	      if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
-						   TREE_TYPE (ref)))
-		return false;
-	      orig[j] = ref;
-	      break;
-	    }
-	  else if (ref == orig[j])
-	    break;
+	  if (orig[1]
+	      && orig[1] != error_mark_node)
+	    return false;
+	  orig[1] = error_mark_node;
+	  if (!one_constant)
+	    one_constant = elt->value;
+	  constants[i] = elt->value;
+	  sel.quick_push (i + nelts);
+	  maybe_ident = false;
 	}
-      if (j == 2)
-	return false;
-
-      unsigned int elt;
-      if (maybe_ne (bit_field_size (op1), elem_size)
-	  || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
+      else
 	return false;
-      if (j)
-	elt += nelts;
-      if (elt != i)
-	maybe_ident = false;
-      sel.quick_push (elt);
     }
   if (i < nelts)
     return false;
@@ -2138,9 +2167,29 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       op2 = vec_perm_indices_to_tree (mask_type, indices);
       if (!orig[1])
 	orig[1] = orig[0];
+      if (orig[1] == error_mark_node)
+	{
+	  tree_vector_builder vec (type, nelts, 1);
+	  for (unsigned i = 0; i < nelts; ++i)
+	    if (constants[i])
+	      vec.quick_push (constants[i]);
+	    else
+	      /* ??? Push a don't-care value.  */
+	      vec.quick_push (one_constant);
+	  orig[1] = vec.build ();
+	}
       if (conv_code == ERROR_MARK)
 	gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
 					orig[1], op2);
+      else if (TREE_CODE (orig[1]) == VECTOR_CST)
+	{
+	  gimple *conv
+	    = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);
+	  orig[0] = gimple_assign_lhs (conv);
+	  gsi_insert_before (gsi, conv, GSI_SAME_STMT);
+	  gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR,
+					  orig[0], orig[1], op2);
+	}
       else
 	{
 	  gimple *perm
-- 
2.20.1

Reply via email to