249 lines
7.2 KiB
Diff
249 lines
7.2 KiB
Diff
|
|
This backport contains 1 patch from gcc main stream tree.
|
||
|
|
The commit id of these patchs list as following in the order of time.
|
||
|
|
|
||
|
|
0001-re-PR-tree-optimization-88828-Inefficient-update-of-.patch
|
||
|
|
3bc104bdb4b5aa99ff6dceb246beaa65b012c5ac
|
||
|
|
|
||
|
|
diff -Nurp a/gcc/testsuite/gcc.target/i386/pr88828-0.c b/gcc/testsuite/gcc.target/i386/pr88828-0.c
|
||
|
|
--- a/gcc/testsuite/gcc.target/i386/pr88828-0.c 1970-01-01 08:00:00.000000000 +0800
|
||
|
|
+++ b/gcc/testsuite/gcc.target/i386/pr88828-0.c 2020-08-24 21:08:23.028000000 +0800
|
||
|
|
@@ -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 -Nurp a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
|
||
|
|
--- a/gcc/tree-ssa-forwprop.c 2020-08-24 21:07:59.800000000 +0800
|
||
|
|
+++ b/gcc/tree-ssa-forwprop.c 2020-08-24 21:08:23.028000000 +0800
|
||
|
|
@@ -1997,17 +1997,54 @@ 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
|
||
|
|
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
|
||
|
|
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
|
||
|
|
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))
|
||
|
|
+ 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
|
||
|
|
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
|