[PATCH] Prep for PR88828 fix

Richard Biener rguenther@suse.de
Fri May 3 13:02:00 GMT 2019


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  <rguenther@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;
+	  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
Index: gcc/testsuite/gcc.target/i386/pr88828-0.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr88828-0.c	(nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr88828-0.c	(working copy)
@@ -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" } } */



More information about the Gcc-patches mailing list