From b8aa7083ec7490b69bd69c21e728f381f6cd4fc3 Mon Sep 17 00:00:00 2001 From: Yuri Rumyantsev Date: Thu, 29 Jan 2015 13:52:28 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 11 +++ gcc/testsuite/ChangeLog | 5 + .../gcc.target/i386/avx2-vect-aggressive-1.c | 33 +++++++ gcc/tree-if-conv.c | 96 +++++++++++++++---- 4 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index be590e5aa99..7424d9faa42 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-01-29 Yuri Rumyantsev + + 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. + 2015-01-29 Richard Biener PR tree-optimization/64853 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8409b469634..69488ec0106 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-01-29 Yuri Rumyantsev + + PR tree-optimization/64746 + * gcc.target/i386/avx2-vect-aggressive-1.c: New test. + 2015-01-29 Richard Biener PR tree-optimization/64853 diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c b/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c new file mode 100644 index 00000000000..a9a88e12a3b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target avx2 } */ +/* { dg-options "-mavx2 -O3 -fopenmp-simd -fdump-tree-vect-details" } */ + +#define N 256 +int a1[N], a2[N], a3[N], a4[N], a5[N], a6[N], a7[N]; + +void foo() +{ + int x1, x2, x3; + int i; +#pragma omp simd safelen(8) + for (i=0; i= 0 && x1 != 3) + { + x2 = a3[i] - a1[i]; + if (x2 >= 0 && x2 != 4) + { + x3 = a4[i] + a5[i]; + if (x3 >= 0 && x3 != 5) + { + a6[i] = x1 - x2; + a7[i] = x3 + x2; + } + } + } + } +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index ade692a39ae..400ee01a512 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 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 vect_sizes; + auto_vec 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 *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 defuse_list = vNULL; + vec 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 -- 2.30.2