On Fri, May 19, 2017 at 1:51 PM, Richard Biener <richard.guent...@gmail.com> wrote: > On Mon, May 15, 2017 at 5:58 PM, Bin.Cheng <amker.ch...@gmail.com> wrote: >> On Thu, May 11, 2017 at 12:02 PM, Richard Biener >> <richard.guent...@gmail.com> wrote: >>> On Tue, Apr 18, 2017 at 12:54 PM, Bin Cheng <bin.ch...@arm.com> wrote >>>> Hi, >>>> Based on vect_peeling algorithm, we know for sure that vectorized loop >>>> must iterates at least once. >>>> This patch sets range information for niter bounds of vectorized loop. >>>> This helps niter analysis, >>>> so iv elimination too. >>>> Is it OK? >>> >>> niters_vector = force_gimple_operand (niters_vector, &stmts, true, >>> var); >>> gsi_insert_seq_on_edge_immediate (pe, stmts); >>> + /* Peeling algorithm guarantees that vector loop bound is at least >>> ONE, >>> + we set range information to make niters analyzer's life easier. */ >>> + if (TREE_CODE (niters_vector) == SSA_NAME) >>> + set_range_info (niters_vector, VR_RANGE, build_int_cst (type, 1), >>> + fold_build2 (RSHIFT_EXPR, type, >>> + TYPE_MAX_VALUE (type), log_vf)); >>> >>> if all of niters_vector folds to an original SSA name then >>> niters_vector after gimplification >>> is not a new SSA name and thus you can't set range-info on it. >>> >>> Likewise for the other case where LOOP_VINFO_NITERS is just an SSA name. >> Hi, >> This is updated patch. It checks whether the result ssa name is newly >> created tmp and only sets range information if so. >> >> Is it OK? > > A better way to check whether the SSA name is new is to see if 'stmts' > filled by force_gimple_operand is non-empty. Hi, Here is updated patch checking empty gimple_seq. Is it OK?
Thanks, bin > > Richard. > >> Thanks, >> bin >> >> 2017-04-11 Bin Cheng <bin.ch...@arm.com> >> >> * tree-vectorizer.h (vect_build_loop_niters): New parameter. >> * tree-vect-loop-manip.c (vect_build_loop_niters): New parameter. >> Set true to new parameter if new ssa variable is defined. >> (vect_gen_vector_loop_niters): Refactor. Set range information >> for the new vector loop bound variable. >> (vect_do_peeling): Ditto. >> >>> >>> Richard. >>> >>>> Thanks, >>>> bin >>>> 2017-04-11 Bin Cheng <bin.ch...@arm.com> >>>> >>>> * tree-vect-loop-manip.c (vect_gen_vector_loop_niters): Refactor. >>>> Set range information for vector loop bound variable. >>>> (vect_do_peeling): Ditto.
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index f48336b..93c1542 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -1095,10 +1095,11 @@ vect_update_inits_of_drs (loop_vec_info loop_vinfo, tree niters) /* This function builds ni_name = number of iterations. Statements - are emitted on the loop preheader edge. */ + are emitted on the loop preheader edge. If NEW_VAR_P is not NULL, set + it to TRUE if new ssa_var is generated. */ tree -vect_build_loop_niters (loop_vec_info loop_vinfo) +vect_build_loop_niters (loop_vec_info loop_vinfo, bool *new_var_p) { tree ni = unshare_expr (LOOP_VINFO_NITERS (loop_vinfo)); if (TREE_CODE (ni) == INTEGER_CST) @@ -1112,7 +1113,11 @@ vect_build_loop_niters (loop_vec_info loop_vinfo) var = create_tmp_var (TREE_TYPE (ni), "niters"); ni_name = force_gimple_operand (ni, &stmts, false, var); if (stmts) - gsi_insert_seq_on_edge_immediate (pe, stmts); + { + gsi_insert_seq_on_edge_immediate (pe, stmts); + if (new_var_p != NULL) + *new_var_p = true; + } return ni_name; } @@ -1177,22 +1182,21 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, tree *niters_vector_ptr, bool niters_no_overflow) { tree ni_minus_gap, var; - tree niters_vector; + tree niters_vector, type = TREE_TYPE (niters); int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); edge pe = loop_preheader_edge (LOOP_VINFO_LOOP (loop_vinfo)); - tree log_vf = build_int_cst (TREE_TYPE (niters), exact_log2 (vf)); + tree log_vf = build_int_cst (type, exact_log2 (vf)); /* If epilogue loop is required because of data accesses with gaps, we subtract one iteration from the total number of iterations here for correct calculation of RATIO. */ if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)) { - ni_minus_gap = fold_build2 (MINUS_EXPR, TREE_TYPE (niters), - niters, - build_one_cst (TREE_TYPE (niters))); + ni_minus_gap = fold_build2 (MINUS_EXPR, type, niters, + build_one_cst (type)); if (!is_gimple_val (ni_minus_gap)) { - var = create_tmp_var (TREE_TYPE (niters), "ni_gap"); + var = create_tmp_var (type, "ni_gap"); gimple *stmts = NULL; ni_minus_gap = force_gimple_operand (ni_minus_gap, &stmts, true, var); @@ -1208,25 +1212,28 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, (niters - vf) >> log2(vf) + 1 by using the fact that we know ratio will be at least one. */ if (niters_no_overflow) - niters_vector = fold_build2 (RSHIFT_EXPR, TREE_TYPE (niters), - ni_minus_gap, log_vf); + niters_vector = fold_build2 (RSHIFT_EXPR, type, ni_minus_gap, log_vf); else niters_vector - = fold_build2 (PLUS_EXPR, TREE_TYPE (niters), - fold_build2 (RSHIFT_EXPR, TREE_TYPE (niters), - fold_build2 (MINUS_EXPR, TREE_TYPE (niters), - ni_minus_gap, - build_int_cst - (TREE_TYPE (niters), vf)), + = fold_build2 (PLUS_EXPR, type, + fold_build2 (RSHIFT_EXPR, type, + fold_build2 (MINUS_EXPR, type, ni_minus_gap, + build_int_cst (type, vf)), log_vf), - build_int_cst (TREE_TYPE (niters), 1)); + build_int_cst (type, 1)); if (!is_gimple_val (niters_vector)) { - var = create_tmp_var (TREE_TYPE (niters), "bnd"); - gimple *stmts = NULL; + var = create_tmp_var (type, "bnd"); + gimple_seq stmts = NULL; niters_vector = force_gimple_operand (niters_vector, &stmts, true, var); gsi_insert_seq_on_edge_immediate (pe, stmts); + /* Peeling algorithm guarantees that vector loop bound is at least ONE, + we set range information to make niters analyzer's life easier. */ + if (stmts != NULL) + set_range_info (niters_vector, VR_RANGE, build_int_cst (type, 1), + fold_build2 (RSHIFT_EXPR, type, + TYPE_MAX_VALUE (type), log_vf)); } *niters_vector_ptr = niters_vector; @@ -1771,7 +1778,13 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, LOOP_VINFO_NITERSM1 (loop_vinfo) = fold_build2 (MINUS_EXPR, type, LOOP_VINFO_NITERSM1 (loop_vinfo), niters_prolog); - niters = vect_build_loop_niters (loop_vinfo); + bool new_var_p = false; + niters = vect_build_loop_niters (loop_vinfo, &new_var_p); + /* It's guaranteed that vector loop bound before vectorization is at + least VF, so set range information for newly generated var. */ + if (new_var_p) + set_range_info (niters, VR_RANGE, + build_int_cst (type, vf), TYPE_MAX_VALUE (type)); /* Prolog iterates at most bound_prolog times, latch iterates at most bound_prolog - 1 times. */ diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 12bb904..f72a1d5 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1168,7 +1168,7 @@ extern gimple *vect_force_simple_reduction (loop_vec_info, gimple *, bool, bool *, bool); /* Drive for loop analysis stage. */ extern loop_vec_info vect_analyze_loop (struct loop *, loop_vec_info); -extern tree vect_build_loop_niters (loop_vec_info); +extern tree vect_build_loop_niters (loop_vec_info, bool * = NULL); extern void vect_gen_vector_loop_niters (loop_vec_info, tree, tree *, bool); /* Drive for loop transformation stage. */ extern struct loop *vect_transform_loop (loop_vec_info);