aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-05-14 09:11:15 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-05-14 09:11:15 +0000
commit962372f9f853c582c879f11c0db14973cc8687e0 (patch)
treeef30e0b7d85731711c60f9e78a158ffb7d2b1c4b /gcc/tree-ssa-forwprop.c
parenta52cf5cf278e4a9e58bfa2bb67a93244766a122f (diff)
downloadgcc-962372f9f853c582c879f11c0db14973cc8687e0.zip
gcc-962372f9f853c582c879f11c0db14973cc8687e0.tar.gz
gcc-962372f9f853c582c879f11c0db14973cc8687e0.tar.bz2
re PR tree-optimization/88828 (Inefficient update of the first element of vector registers)
2019-05-14 Richard Biener <rguenther@suse.de> H.J. Lu <hongjiu.lu@intel.com> PR tree-optimization/88828 * tree-ssa-forwprop.c (simplify_vector_constructor): Handle permuting in a single non-constant element not extracted from a vector. * gcc.target/i386/pr88828-1.c: New test. * gcc.target/i386/pr88828-1a.c: Likewise. * gcc.target/i386/pr88828-1b.c: Likewise. * gcc.target/i386/pr88828-1c.c: Likewise. * gcc.target/i386/pr88828-4a.c: Likewise. * gcc.target/i386/pr88828-4b.c: Likewise. * gcc.target/i386/pr88828-5a.c: Likewise. * gcc.target/i386/pr88828-5b.c: Likewise. * gcc.target/i386/pr88828-7.c: Likewise. * gcc.target/i386/pr88828-7a.c: Likewise. * gcc.target/i386/pr88828-7b.c: Likewise. * gcc.target/i386/pr88828-8.c: Likewise. * gcc.target/i386/pr88828-8a.c: Likewise. * gcc.target/i386/pr88828-8b.c: Likewise. * gcc.target/i386/pr88828-9.c: Likewise. * gcc.target/i386/pr88828-9a.c: Likewise. * gcc.target/i386/pr88828-9b.c: Likewise. Co-Authored-By: H.J. Lu <hongjiu.lu@intel.com> From-SVN: r271153
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c97
1 files changed, 62 insertions, 35 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 32b5a15..b6b21f8 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2065,71 +2065,87 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
conv_code = ERROR_MARK;
maybe_ident = true;
tree one_constant = NULL_TREE;
+ tree one_nonconstant = NULL_TREE;
auto_vec<tree> constants;
constants.safe_grow_cleared (nelts);
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
{
tree ref, op1;
+ unsigned int elem;
if (i >= nelts)
return false;
+ /* Look for elements extracted and possibly converted from
+ another vector. */
op1 = get_bit_field_ref_def (elt->value, conv_code);
- if (op1)
+ if (op1
+ && TREE_CODE ((ref = TREE_OPERAND (op1, 0))) == SSA_NAME
+ && VECTOR_TYPE_P (TREE_TYPE (ref))
+ && useless_type_conversion_p (TREE_TYPE (op1),
+ TREE_TYPE (TREE_TYPE (ref)))
+ && known_eq (bit_field_size (op1), elem_size)
+ && constant_multiple_p (bit_field_offset (op1),
+ elem_size, &elem))
{
- ref = TREE_OPERAND (op1, 0);
unsigned int j;
for (j = 0; j < 2; ++j)
{
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;
+ if (j == 0
+ || useless_type_conversion_p (TREE_TYPE (orig[0]),
+ TREE_TYPE (ref)))
+ break;
}
else if (ref == orig[j])
break;
}
- 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);
+ /* Found a suitable vector element. */
+ if (j <= 2)
+ {
+ orig[j] = ref;
+ if (j)
+ elem += nelts;
+ if (elem != i)
+ maybe_ident = false;
+ sel.quick_push (elem);
+ continue;
+ }
+ /* Else fallthru. */
}
- else if (CONSTANT_CLASS_P (elt->value))
+ /* Handle elements not extracted from a vector.
+ 1. constants by permuting with constant vector
+ 2. a unique non-constant element by permuting with a splat vector */
+ if (orig[1]
+ && orig[1] != error_mark_node)
+ return false;
+ orig[1] = error_mark_node;
+ if (CONSTANT_CLASS_P (elt->value))
{
- if (orig[1]
- && orig[1] != error_mark_node)
+ if (one_nonconstant)
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;
}
else
- return false;
+ {
+ if (one_constant)
+ return false;
+ if (!one_nonconstant)
+ one_nonconstant = elt->value;
+ else if (!operand_equal_p (one_nonconstant, elt->value, 0))
+ return false;
+ }
+ sel.quick_push (i + nelts);
+ maybe_ident = false;
}
if (i < nelts)
return false;
- if (! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
+ if (! orig[0]
+ || ! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
|| maybe_ne (TYPE_VECTOR_SUBPARTS (type),
TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig[0]))))
return false;
@@ -2165,9 +2181,19 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
GET_MODE_SIZE (TYPE_MODE (type))))
return false;
op2 = vec_perm_indices_to_tree (mask_type, indices);
+ bool convert_orig0 = false;
if (!orig[1])
orig[1] = orig[0];
- if (orig[1] == error_mark_node)
+ else if (orig[1] == error_mark_node
+ && one_nonconstant)
+ {
+ gimple_seq seq = NULL;
+ orig[1] = gimple_build_vector_from_val (&seq, UNKNOWN_LOCATION,
+ type, one_nonconstant);
+ gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+ convert_orig0 = true;
+ }
+ else if (orig[1] == error_mark_node)
{
tree_vector_builder vec (type, nelts, 1);
for (unsigned i = 0; i < nelts; ++i)
@@ -2177,11 +2203,12 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
/* ??? Push a don't-care value. */
vec.quick_push (one_constant);
orig[1] = vec.build ();
+ convert_orig0 = true;
}
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)
+ else if (convert_orig0)
{
gimple *conv
= gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);