On Thu, 11 Jan 2024, Tamar Christina wrote: > Hi All, > > When we have a loop with more than 2 exits and a reduction I forgot to fill in > the PHI value for all alternate exits. > > All alternate exits use the same PHI value so we should loop over the new > PHI elements and copy the value across since we call the reduction calculation > code only once for all exits. This was normally covered up by earlier parts > of > the compiler rejecting loops incorrectly (which has been fixed now). > > Note that while I can use the loop in all cases, the reason I separated out > the > main and alt exit is so that if you pass the wrong edge the macro will assert. > > Bootstrapped Regtested on aarch64-none-linux-gnu, x86_64-pc-linux-gnu > and no issues. > > Ok for master?
OK > Thanks, > Tamar > > gcc/ChangeLog: > > PR tree-optimization/113178 > * tree-vect-loop.cc (vect_create_epilog_for_reduction): Fill in all > alternate exits. > > gcc/testsuite/ChangeLog: > > PR tree-optimization/113178 > * g++.dg/vect/vect-early-break_6-pr113178.cc: New test. > * gcc.dg/vect/vect-early-break_101-pr113178.c: New test. > * gcc.dg/vect/vect-early-break_102-pr113178.c: New test. > > --- inline copy of patch -- > diff --git a/gcc/testsuite/g++.dg/vect/vect-early-break_6-pr113178.cc > b/gcc/testsuite/g++.dg/vect/vect-early-break_6-pr113178.cc > new file mode 100644 > index > 0000000000000000000000000000000000000000..da008759a72dd563bf4930decd74470ae35cb98e > --- /dev/null > +++ b/gcc/testsuite/g++.dg/vect/vect-early-break_6-pr113178.cc > @@ -0,0 +1,34 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > + > +struct PixelWeight { > + int m_SrcStart; > + int m_Weights[]; > +}; > +struct CWeightTable { > + int *GetValueFromPixelWeight(PixelWeight *, int) const; > +}; > +char ContinueStretchHorz_dest_scan; > +struct CStretchEngine { > + bool ContinueStretchHorz(); > + CWeightTable m_WeightTable; > +}; > +int *CWeightTable::GetValueFromPixelWeight(PixelWeight *pWeight, > + int index) const { > + long __trans_tmp_1; > + if (index < pWeight->m_SrcStart) > + return __trans_tmp_1 ? &pWeight->m_Weights[pWeight->m_SrcStart] : > nullptr; > +} > +bool CStretchEngine::ContinueStretchHorz() { > + { > + PixelWeight pPixelWeights; > + int dest_g_m; > + for (int j; j; j++) { > + int pWeight = *m_WeightTable.GetValueFromPixelWeight(&pPixelWeights, > j); > + dest_g_m += pWeight; > + } > + ContinueStretchHorz_dest_scan = dest_g_m; > + } > +} > diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_101-pr113178.c > b/gcc/testsuite/gcc.dg/vect/vect-early-break_101-pr113178.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..8b91112133f0522270bb4d92664355838a405aaf > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_101-pr113178.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > + > +struct PixelWeight { > + int m_SrcStart; > + int m_Weights[16]; > +}; > +char h; > +void f(struct PixelWeight *pPixelWeights) { > + int dest_g_m; > + long tt; > + for (int j = 0; j < 16; j++) { > + int *p = 0; > + if (j < pPixelWeights->m_SrcStart) > + p = tt ? &pPixelWeights->m_Weights[0] : 0; > + int pWeight = *p; > + dest_g_m += pWeight; > + } > + h = dest_g_m; > +} > diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_102-pr113178.c > b/gcc/testsuite/gcc.dg/vect/vect-early-break_102-pr113178.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..ad7582e440720e50a2769239c88b1e07517e4c10 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_102-pr113178.c > @@ -0,0 +1,19 @@ > +/* { dg-do compile } */ > +/* { dg-add-options vect_early_break } */ > +/* { dg-require-effective-target vect_early_break } */ > +/* { dg-require-effective-target vect_int } */ > +/* { dg-additional-options "-std=gnu99 -fpermissive -fgnu89-inline -Ofast > -fprofile-generate -w" } */ > + > +extern int replace_reg_with_saved_mem_i, replace_reg_with_saved_mem_nregs, > + replace_reg_with_saved_mem_mem_1; > +replace_reg_with_saved_mem_mode() { > + if (replace_reg_with_saved_mem_i) > + return; > + while (++replace_reg_with_saved_mem_i < replace_reg_with_saved_mem_nregs) > + if (replace_reg_with_saved_mem_i) > + break; > + if (replace_reg_with_saved_mem_i) > + if (replace_reg_with_saved_mem_mem_1) > + adjust_address_1(); > + replace_reg_with_saved_mem_mem_1 ? fancy_abort() : 0; > +} > diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc > index > 27bb28365936978013a576b64b72d9e92375f361..da2dfa176ecd457ebc11d1131302ca15d77d779d > 100644 > --- a/gcc/tree-vect-loop.cc > +++ b/gcc/tree-vect-loop.cc > @@ -6223,7 +6223,13 @@ vect_create_epilog_for_reduction (loop_vec_info > loop_vinfo, > phi = create_phi_node (new_def, exit_bb); > if (j) > def = gimple_get_lhs (vec_stmts[j]); > - SET_PHI_ARG_DEF (phi, loop_exit->dest_idx, def); > + if (LOOP_VINFO_IV_EXIT (loop_vinfo) == loop_exit) > + SET_PHI_ARG_DEF (phi, loop_exit->dest_idx, def); > + else > + { > + for (unsigned k = 0; k < gimple_phi_num_args (phi); k++) > + SET_PHI_ARG_DEF (phi, k, def); > + } > new_def = gimple_convert (&stmts, vectype, new_def); > reduc_inputs.quick_push (new_def); > } > > > > > -- 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)