diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-22 14:55:48 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-22 14:55:48 +0000 |
commit | e80e26dbccf3025687e6ff283d3b0ea3df323e31 (patch) | |
tree | fa066c45b21e099c0fd6d70615ac22a7b64cf45a /gcc/tree-vect-generic.c | |
parent | c29bc60ba5560af4a645eeab1f350b470ee09513 (diff) | |
parent | 8b450f8859f22b0d3afa8edb42f3f287400d6975 (diff) | |
download | gcc-e80e26dbccf3025687e6ff283d3b0ea3df323e31.tar.gz |
Merge with trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@205263 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r-- | gcc/tree-vect-generic.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 50ee7d78a11..367992671af 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -984,6 +984,84 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type gimple_assign_rhs1 (assign), gimple_assign_rhs2 (assign), code); } + +/* Try to optimize + a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 }; + style stmts into: + _9 = { b_7, b_7, b_7, b_7 }; + a_5 = _9 + { 0, 3, 6, 9 }; + because vector splat operation is usually more efficient + than piecewise initialization of the vector. */ + +static void +optimize_vector_constructor (gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + tree type = TREE_TYPE (rhs); + unsigned int i, j, nelts = TYPE_VECTOR_SUBPARTS (type); + bool all_same = true; + constructor_elt *elt; + tree *cst; + gimple g; + tree base = NULL_TREE; + + if (nelts <= 2 || CONSTRUCTOR_NELTS (rhs) != nelts) + return; + FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt) + if (TREE_CODE (elt->value) != SSA_NAME + || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE) + return; + else + { + tree this_base = elt->value; + if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value) + all_same = false; + for (j = 0; j < nelts + 1; j++) + { + g = SSA_NAME_DEF_STMT (this_base); + if (is_gimple_assign (g) + && gimple_assign_rhs_code (g) == PLUS_EXPR + && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST + && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g))) + this_base = gimple_assign_rhs1 (g); + else + break; + } + if (i == 0) + base = this_base; + else if (this_base != base) + return; + } + if (all_same) + return; + cst = XALLOCAVEC (tree, nelts); + for (i = 0; i < nelts; i++) + { + tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;; + cst[i] = build_zero_cst (TREE_TYPE (base)); + while (this_base != base) + { + g = SSA_NAME_DEF_STMT (this_base); + cst[i] = fold_binary (PLUS_EXPR, TREE_TYPE (base), + cst[i], gimple_assign_rhs2 (g)); + if (cst[i] == NULL_TREE + || TREE_CODE (cst[i]) != INTEGER_CST + || TREE_OVERFLOW (cst[i])) + return; + this_base = gimple_assign_rhs1 (g); + } + } + for (i = 0; i < nelts; i++) + CONSTRUCTOR_ELT (rhs, i)->value = base; + g = gimple_build_assign (make_ssa_name (type, NULL), rhs); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign_with_ops (PLUS_EXPR, lhs, gimple_assign_lhs (g), + build_vector (type, cst)); + gsi_replace (gsi, g, false); +} /* Return a type for the widest vector mode whose components are of type TYPE, or NULL_TREE if none is found. */ @@ -1274,6 +1352,17 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) expand_vector_condition (gsi); return; } + + if (code == CONSTRUCTOR + && TREE_CODE (lhs) == SSA_NAME + && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs))) + && !gimple_clobber_p (stmt) + && optimize) + { + optimize_vector_constructor (gsi); + return; + } + if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS) return; |