Commit 3bc104bd by Richard Biener Committed by Richard Biener

re PR tree-optimization/88828 (Inefficient update of the first element of vector registers)

2019-05-06  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.

From-SVN: r270908
parent 1d0b81c6
2019-05-06 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.
2019-05-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/90328
* tree-data-ref.h (dr_may_alias_p): Pass in the actual loop nest.
* tree-data-ref.c (dr_may_alias_p): Check whether the clique
......
2019-05-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/88828
* gcc.target/i386/pr88828-0.c: New testcase.
2019-05-06 Richard Biener <rguenther@suse.de>
PR tree-optimization/90328
* gcc.dg/torture/pr90328.c: New testcase.
......
/* { 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" } } */
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment