diff options
author | Richard Biener <rguenther@suse.de> | 2019-05-14 09:11:15 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2019-05-14 09:11:15 +0000 |
commit | 962372f9f853c582c879f11c0db14973cc8687e0 (patch) | |
tree | ef30e0b7d85731711c60f9e78a158ffb7d2b1c4b /gcc/tree-ssa-forwprop.c | |
parent | a52cf5cf278e4a9e58bfa2bb67a93244766a122f (diff) | |
download | gcc-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.c | 97 |
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]); |