diff options
author | Yuri Rumyantsev <ysrumyan@gmail.com> | 2015-01-29 13:52:28 +0000 |
---|---|---|
committer | Ilya Enkovich <ienkovich@gcc.gnu.org> | 2015-01-29 13:52:28 +0000 |
commit | b8aa7083ec7490b69bd69c21e728f381f6cd4fc3 (patch) | |
tree | 580d0bf030254594d77906cd1a8f4404e385f004 /gcc/tree-if-conv.c | |
parent | d94e3e750d1e5c2fc9ecc8e8a32adec33fc85f8e (diff) | |
download | gcc-b8aa7083ec7490b69bd69c21e728f381f6cd4fc3.zip gcc-b8aa7083ec7490b69bd69c21e728f381f6cd4fc3.tar.gz gcc-b8aa7083ec7490b69bd69c21e728f381f6cd4fc3.tar.bz2 |
re PR tree-optimization/64746 (Loop with nested load/stores is not vectorized using aggressive if-conversion.)
gcc/
PR tree-optimization/64746
* tree-if-conv.c (mask_exists): New function.
(predicate_mem_writes): Save created mask with given size for further
use.
(stmt_is_root_of_bool_pattern): Remove argument VAR and store to it.
(ifcvt_repair_bool_pattern): Collect all statements that are root
of bool pattern and use iterative algorithm to remove multiple uses
of predicates, display number of required iterations.
gcc/testsuite/
PR tree-optimization/64746
* gcc.target/i386/avx2-vect-aggressive-1.c: New test.
From-SVN: r220248
Diffstat (limited to 'gcc/tree-if-conv.c')
-rw-r--r-- | gcc/tree-if-conv.c | 96 |
1 files changed, 75 insertions, 21 deletions
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index ade692a..400ee01 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -1974,6 +1974,20 @@ insert_gimplified_predicates (loop_p loop, bool any_mask_load_store) } } +/* Helper function for predicate_mem_writes. Returns index of existent + mask if it was created for given SIZE and -1 otherwise. */ + +static int +mask_exists (int size, vec<int> vec) +{ + unsigned int ix; + int v; + FOR_EACH_VEC_ELT (vec, ix, v) + if (v == size) + return (int) ix; + return -1; +} + /* Predicate each write to memory in LOOP. This function transforms control flow constructs containing memory @@ -2085,6 +2099,8 @@ static void predicate_mem_writes (loop_p loop) { unsigned int i, orig_loop_num_nodes = loop->num_nodes; + auto_vec<int, 1> vect_sizes; + auto_vec<tree, 1> vect_masks; for (i = 1; i < orig_loop_num_nodes; i++) { @@ -2093,6 +2109,7 @@ predicate_mem_writes (loop_p loop) tree cond = bb_predicate (bb); bool swap; gimple stmt; + int index; if (is_true_predicate (cond)) continue; @@ -2104,6 +2121,9 @@ predicate_mem_writes (loop_p loop) cond = TREE_OPERAND (cond, 0); } + vect_sizes.truncate (0); + vect_masks.truncate (0); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) if (!gimple_assign_single_p (stmt = gsi_stmt (gsi))) continue; @@ -2114,21 +2134,31 @@ predicate_mem_writes (loop_p loop) tree ref, addr, ptr, masktype, mask_op0, mask_op1, mask; gimple new_stmt; int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs))); - - masktype = build_nonstandard_integer_type (bitsize, 1); - mask_op0 = build_int_cst (masktype, swap ? 0 : -1); - mask_op1 = build_int_cst (masktype, swap ? -1 : 0); ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; mark_addressable (ref); addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref), true, NULL_TREE, true, GSI_SAME_STMT); - cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - mask = fold_build_cond_expr (masktype, unshare_expr (cond), - mask_op0, mask_op1); - mask = ifc_temp_var (masktype, mask, &gsi); + if (!vect_sizes.is_empty () + && (index = mask_exists (bitsize, vect_sizes)) != -1) + /* Use created mask. */ + mask = vect_masks[index]; + else + { + masktype = build_nonstandard_integer_type (bitsize, 1); + mask_op0 = build_int_cst (masktype, swap ? 0 : -1); + mask_op1 = build_int_cst (masktype, swap ? -1 : 0); + cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), + is_gimple_condexpr, + NULL_TREE, + true, GSI_SAME_STMT); + mask = fold_build_cond_expr (masktype, unshare_expr (cond), + mask_op0, mask_op1); + mask = ifc_temp_var (masktype, mask, &gsi); + /* Save mask and its size for further use. */ + vect_sizes.safe_push (bitsize); + vect_masks.safe_push (mask); + } ptr = build_int_cst (reference_alias_ptr_type (ref), 0); /* Copy points-to info if possible. */ if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)) @@ -2494,10 +2524,10 @@ ifcvt_walk_pattern_tree (tree var, vec<gimple> *defuse_list, } /* Returns true if STMT can be a root of bool pattern apllied - by vectorizer. VAR contains SSA_NAME which starts pattern. */ + by vectorizer. */ static bool -stmt_is_root_of_bool_pattern (gimple stmt, tree *var) +stmt_is_root_of_bool_pattern (gimple stmt) { enum tree_code code; tree lhs, rhs; @@ -2511,7 +2541,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var) return false; if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE) return false; - *var = rhs; return true; } else if (code == COND_EXPR) @@ -2519,7 +2548,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var) rhs = gimple_assign_rhs1 (stmt); if (TREE_CODE (rhs) != SSA_NAME) return false; - *var = rhs; return true; } return false; @@ -2538,23 +2566,49 @@ ifcvt_repair_bool_pattern (basic_block bb) gimple stmt; gimple_stmt_iterator gsi; vec<gimple> defuse_list = vNULL; + vec<gimple> pattern_roots = vNULL; + bool repeat = true; + int niter = 0; + unsigned int ix; + /* Collect all root pattern statements. */ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { stmt = gsi_stmt (gsi); if (gimple_code (stmt) != GIMPLE_ASSIGN) continue; - if (!stmt_is_root_of_bool_pattern (stmt, &rhs)) + if (!stmt_is_root_of_bool_pattern (stmt)) continue; - ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt); - while (defuse_list.length () > 0) + pattern_roots.safe_push (stmt); + } + + if (pattern_roots.is_empty ()) + return; + + /* Split all statements with multiple uses iteratively since splitting + may create new multiple uses. */ + while (repeat) + { + repeat = false; + niter++; + FOR_EACH_VEC_ELT (pattern_roots, ix, stmt) { - gimple def_stmt, use_stmt; - use_stmt = defuse_list.pop (); - def_stmt = defuse_list.pop (); - ifcvt_split_def_stmt (def_stmt, use_stmt); + rhs = gimple_assign_rhs1 (stmt); + ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt); + while (defuse_list.length () > 0) + { + repeat = true; + gimple def_stmt, use_stmt; + use_stmt = defuse_list.pop (); + def_stmt = defuse_list.pop (); + ifcvt_split_def_stmt (def_stmt, use_stmt); + } + } } + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Repair bool pattern takes %d iterations. \n", + niter); } /* Delete redundant statements produced by predication which prevents |