On Mon, Jun 12, 2017 at 6:02 PM, Bin Cheng <bin.ch...@arm.com> wrote: > Hi, > I was asked by upstream to split the loop distribution patch into small ones. > It is hard because data structure and algorithm are closely coupled together. > Anyway, this is the patch series with smaller patches. Basically I tried to > separate data structure and bug-fix changes apart with one as the main patch. > Note I only made necessary code refactoring in order to separate patch, apart > from that, there is no change against the last version. > > This is the first patch introducing new internal function IFN_LOOP_DIST_ALIAS. > GCC will distribute loops under condition of this function call. > > Bootstrap and test on x86_64 and AArch64. Is it OK? Hi, I need to update this patch fixing an issue in vect_loop_dist_alias_call. The previous patch fails to find some IFN_LOOP_DIST_ALIAS calls.
Bootstrap and test in series. Is it OK? Thanks, bin > > Thanks, > bin > 2017-06-07 Bin Cheng <bin.ch...@arm.com> > > * cfgloop.h (struct loop): New field ldist_alias_id. > * cfgloopmanip.c (lv_adjust_loop_entry_edge): Comment change. > * internal-fn.c (expand_LOOP_DIST_ALIAS): New function. > * internal-fn.def (LOOP_DIST_ALIAS): New. > * tree-vectorizer.c (vect_loop_dist_alias_call): New function. > (fold_loop_dist_alias_call): New function. > (vectorize_loops): Fold IFN_LOOP_DIST_ALIAS call depending on > successful vectorization or not.
From ab8334c5f109c593610df3efcf1aa5a2edcf6be9 Mon Sep 17 00:00:00 2001 From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com> Date: Wed, 7 Jun 2017 13:04:03 +0100 Subject: [PATCH 01/13] ifn_loop_dist_alias-20170608.txt --- gcc/cfgloop.h | 9 ++++++ gcc/cfgloopmanip.c | 3 +- gcc/internal-fn.c | 8 ++++++ gcc/internal-fn.def | 1 + gcc/tree-vectorizer.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index a8bec1d..be4187a 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -225,6 +225,15 @@ struct GTY ((chain_next ("%h.next"))) loop { builtins. */ tree simduid; + /* For loops generated by distribution with runtime alias checks, this + is a unique identifier of the original distributed loop. Generally + it is the number of the original loop. IFN_LOOP_DIST_ALIAS builtin + uses this id as its first argument. Give a loop with an id, we can + look upward in dominance tree for the corresponding IFN_LOOP_DIST_ALIAS + buildin. Note this id has no meanling after IFN_LOOP_DIST_ALIAS is + folded and eliminated. */ + int ldist_alias_id; + /* Upper bound on number of iterations of a loop. */ struct nb_iter_bound *bounds; diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index d764ab9..adb2f65 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1653,7 +1653,8 @@ force_single_succ_latches (void) THEN_PROB is the probability of then branch of the condition. ELSE_PROB is the probability of else branch. Note that they may be both - REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED. */ + REG_BR_PROB_BASE when condition is IFN_LOOP_VECTORIZED or + IFN_LOOP_DIST_ALIAS. */ static basic_block lv_adjust_loop_entry_edge (basic_block first_head, basic_block second_head, diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 75fe027..96e40cb 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -2250,6 +2250,14 @@ expand_LOOP_VECTORIZED (internal_fn, gcall *) gcc_unreachable (); } +/* This should get folded in tree-vectorizer.c. */ + +static void +expand_LOOP_DIST_ALIAS (internal_fn, gcall *) +{ + gcc_unreachable (); +} + /* Expand MASK_LOAD call STMT using optab OPTAB. */ static void diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index e162d81..79c19fb 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -158,6 +158,7 @@ DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_START, ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_END, ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (LOOP_DIST_ALIAS, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ".R.") DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, NULL) diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 1bef2e4..05e9f84 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -469,6 +469,67 @@ fold_loop_vectorized_call (gimple *g, tree value) } } +/* If LOOP has been versioned during loop distribution, return the internal + call guarding it. */ + +static gimple * +vect_loop_dist_alias_call (struct loop *loop) +{ + gimple_stmt_iterator gsi; + gimple *g; + basic_block bb = loop_preheader_edge (loop)->src; + basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); + struct loop *outer_loop = bb->loop_father; + + /* Look upward in dominance tree. */ + for (; bb != entry && flow_bb_inside_loop_p (outer_loop, bb); + bb = get_immediate_dominator (CDI_DOMINATORS, bb)) + { + if (bb->loop_father != outer_loop) + continue; + + g = last_stmt (bb); + if (g == NULL || gimple_code (g) != GIMPLE_COND) + continue; + + gsi = gsi_for_stmt (g); + gsi_prev (&gsi); + if (gsi_end_p (gsi)) + continue; + + g = gsi_stmt (gsi); + /* The guarding internal function call must have the same distribution + alias id. */ + if (gimple_call_internal_p (g, IFN_LOOP_DIST_ALIAS) + && (tree_to_shwi (gimple_call_arg (g, 0)) == loop->ldist_alias_id)) + return g; + } + return NULL; +} + +/* Fold LOOP_DIST_ALIAS internal call stmt according to KEEP_P and update + any immediate uses of it's LHS. Stmt is folded to its second argument + if KEEP_P is true, otherwise to boolean_false_node. */ + +static void +fold_loop_dist_alias_call (gimple *g, bool keep_p) +{ + tree lhs = gimple_call_lhs (g); + use_operand_p use_p; + imm_use_iterator iter; + gimple *use_stmt; + gimple_stmt_iterator gsi = gsi_for_stmt (g); + tree folded_value = keep_p ? gimple_call_arg (g, 1) : boolean_false_node; + + update_call_from_tree (&gsi, folded_value); + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) + { + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, folded_value); + update_stmt (use_stmt); + } +} + /* Set the uids of all the statements in basic blocks inside loop represented by LOOP_VINFO. LOOP_VECTORIZED_CALL is the internal call guarding the loop which has been if converted. */ @@ -595,7 +656,7 @@ vectorize_loops (void) else { loop_vec_info loop_vinfo, orig_loop_vinfo; - gimple *loop_vectorized_call; + gimple *loop_vectorized_call, *loop_dist_alias_call; try_vectorize: if (!((flag_tree_loop_vectorize && optimize_loop_nest_for_speed_p (loop)) @@ -603,6 +664,7 @@ vectorize_loops (void) continue; orig_loop_vinfo = NULL; loop_vectorized_call = vect_loop_vectorized_call (loop); + loop_dist_alias_call = vect_loop_dist_alias_call (loop); vectorize_epilogue: vect_location = find_loop_location (loop); if (LOCATION_LOCUS (vect_location) != UNKNOWN_LOCATION @@ -710,6 +772,12 @@ vectorize_loops (void) loop_vectorized_call = NULL; ret |= TODO_cleanup_cfg; } + if (loop_dist_alias_call) + { + fold_loop_dist_alias_call (loop_dist_alias_call, true); + loop_dist_alias_call = NULL; + ret |= TODO_cleanup_cfg; + } if (new_loop) { @@ -743,6 +811,15 @@ vectorize_loops (void) { fold_loop_vectorized_call (g, boolean_false_node); ret |= TODO_cleanup_cfg; + g = NULL; + } + else + g = vect_loop_dist_alias_call (loop); + + if (g) + { + fold_loop_dist_alias_call (g, false); + ret |= TODO_cleanup_cfg; } } } -- 1.9.1