> -----Original Message----- > From: Tamar Christina <tamar.christ...@arm.com> > Sent: Wednesday, December 6, 2023 8:48 AM > To: Richard Biener <rguent...@suse.de> > Cc: gcc-patches@gcc.gnu.org; nd <n...@arm.com>; j...@ventanamicro.com > Subject: RE: [PATCH]middle-end: Fix peeled vect loop IV values. > > > > Hi All, > > > > > > While waiting for reviews I found this case where both loop exit needs to > > > go to > > > epilogue loop, but there was an IV related variable that was used in the > > > scalar > > > iteration as well. > > > > > > vect_update_ivs_after_vectorizer then blew the value away and replaced it > > > with > > > the value if it took the normal exit. > > > > > > For these cases where we've peeled an a vector iteration, we should skip > > > vect_update_ivs_after_vectorizer since all exits are "alternate" exits. > > > > > > For this to be correct we have peeling put the right LCSSA variables so > > > vectorable_live_operations takes care of it. > > > > > > This is triggered by new testcases 79 and 80 in early break testsuite > > > and I'll merge this commit in the main one. > > > > > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > > > > > Ok for master? > > > > > > Thanks, > > > Tamar > > > > > > gcc/ChangeLog: > > > > > > * tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg): > > > Put right LCSSA var for peeled vect loops. > > > (vect_do_peeling): Skip vect_update_ivs_after_vectorizer. > > > > > > --- inline copy of patch -- > > > diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc > > > index > > > 7d48502e2e46240553509dfa6d75fcab7fea36d3..bfdbeb7faaba29aad51c0561d > > ace680c96759484 100644 > > > --- a/gcc/tree-vect-loop-manip.cc > > > +++ b/gcc/tree-vect-loop-manip.cc > > > @@ -1668,6 +1668,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop > > *loop, edge loop_exit, > > > edge loop_entry = single_succ_edge (new_preheader); > > > if (flow_loops) > > > { > > > + bool peeled_iters = single_pred (loop->latch) != loop_exit->src; > > > /* Link through the main exit first. */ > > > for (auto gsi_from = gsi_start_phis (loop->header), > > > gsi_to = gsi_start_phis (new_loop->header); > > > @@ -1692,11 +1693,19 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class > > loop *loop, edge loop_exit, > > > continue; > > > } > > > } > > > + /* If we have multiple exits and the vector loop is peeled then we > > > + need to use the value at start of loop. */ > > > > This comment doesn't really match 'peeled_iters'? Iff the main IV exit > > source isn't loop->latch then won't we miscompute? I realize the > > complication is that slpeel_tree_duplicate_loop_to_edge_cfg is used from > > elsewhere as well (so we can't check > LOOP_VINFO_EARLY_BREAKS_VECT_PEELED). > > > > No, because in both exits we restart the scalar iteration at the start of the > last > vector iteration. > Normally, the counted main exit would be updated by vect_iters_bound_vf - vf. > Which is the same > As the induction value should we get to the final iteration. > > More on it in your question below. > > > > + if (peeled_iters) > > > + { > > > + tree tmp_arg = gimple_phi_result (from_phi); > > > + if (!new_phi_args.get (tmp_arg)) > > > + new_arg = tmp_arg; > > > + } > > > > > > tree new_res = copy_ssa_name (gimple_phi_result (from_phi)); > > > gphi *lcssa_phi = create_phi_node (new_res, new_preheader); > > > > > > - /* Main loop exit should use the final iter value. */ > > > + /* Otherwise, main loop exit should use the final iter value. */ > > > SET_PHI_ARG_DEF (lcssa_phi, loop_exit->dest_idx, new_arg); > > > > > > > > adjust_phi_and_debug_stmts > > (to_phi, loop_entry, new_res); > > > @@ -3394,9 +3403,13 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree > > niters, tree nitersm1, > > > if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo)) > > > update_e = single_succ_edge (e->dest); > > > > > > - /* Update the main exit. */ > > > - vect_update_ivs_after_vectorizer (loop_vinfo, > > > niters_vector_mult_vf, > > > - update_e); > > > + /* If we have a peeled vector iteration, all exits are the same, > > > leave it > > > + and so the main exit needs to be treated the same as the alternative > > > + exits in that we leave their updates to vectorizable_live_operations. > > > + */ > > > + if (!LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo)) > > > + vect_update_ivs_after_vectorizer (loop_vinfo, niters_vector_mult_vf, > > > + update_e); > > > > and now we don't update the main exit? What's > > LOOP_VINFO_EARLY_BREAKS_VECT_PEELED again vs. > > LOOP_VINFO_EARLY_BREAKS? > > So LOOP_VINFO_EARLY_BREAKS essentially says that there are multiple exits > That we can vectorize. > > LOOP_VINFO_EARLY_BREAKS_VECT_PEELED is saying that in this loop, we've > picked as the main exit not the loops latch connected exit. This means when > we > exit from the "main" exit in the final iteration we may still have side > effects to > perform and so the final iteration should be restarted. > > Similarly exiting from an early exit in this case also means having to > restart the > Loop at the same place to apply any partial side-effects. This is because in > these > Cases the loop exits at n - 1 iterations, the IV is updated and checked > before the > final exit, so taking an early exit means we still have to apply partial > side-effects. >
As an example, the testcase is __attribute__((noinline, noipa)) int f(x) { int i; for (i = 0; i < 8 && (x & 1) == 0; i++) x >>= 1; return i; } main() { if (f(4) != 2) abort(); exit(0); } Where the value of x also needs to be preserved when we take either exit. Cheers, Tamar > Regards, > Tamar > > > > > if (skip_epilog || LOOP_VINFO_EARLY_BREAKS (loop_vinfo)) > > > { > > > > > > > > > > > > > > > > > > > -- > > Richard Biener <rguent...@suse.de> > > SUSE Software Solutions Germany GmbH, > > Frankenstrasse 146, 90461 Nuernberg, Germany; > > GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)