[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