aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-05-06 12:43:30 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-05-06 12:43:30 +0000
commit3bc104bdb4b5aa99ff6dceb246beaa65b012c5ac (patch)
tree39d90f77cf71421e0b2a609962fafac564d85c84 /gcc
parent1d0b81c64c05f40b94bd221558d0339c732d8cc4 (diff)
downloadgcc-3bc104bdb4b5aa99ff6dceb246beaa65b012c5ac.zip
gcc-3bc104bdb4b5aa99ff6dceb246beaa65b012c5ac.tar.gz
gcc-3bc104bdb4b5aa99ff6dceb246beaa65b012c5ac.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-0.c27
-rw-r--r--gcc/tree-ssa-forwprop.c159
4 files changed, 143 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b4424dd..3e9b69b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2ad2c4a..3788739 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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.
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 0000000..3ddb2d1
--- /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 1553c9e..7dd1e64 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