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 <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)