On Mon, 5 Feb 2024, Tamar Christina wrote:

> Hi All,
> 
> The report shows that if the FE leaves a label as the first thing in the dest
> BB then we ICE because we move the stores before the label.
> 
> This is easy to fix if we know that there's still only one way into the BB.
> We would have already rejected the loop if there was multiple paths into the 
> BB
> however I added an additional check just for early break in case the other
> constraints are relaxed later with an explanation.
> 
> After that we fix the issue just by getting the GSI after the labels and I add
> a bunch of testcases for different positions the label can be added.  Only the
> vect-early-break_112-pr113750.c one results in the label being kept.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> 
> Ok for master?

OK.  I'll note the extra check is likely redundant with the one
for in-loop diamonds.

Thanks,
Richard.

> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
>       PR tree-optimization/113750
>       * tree-vect-data-refs.cc (vect_analyze_early_break_dependences): Check
>       for single predecessor when doing early break vect.
>       * tree-vect-loop.cc (move_early_exit_stmts): Get gsi at the start but
>       after labels.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR tree-optimization/113750
>       * gcc.dg/vect/vect-early-break_112-pr113750.c: New test.
>       * gcc.dg/vect/vect-early-break_113-pr113750.c: New test.
>       * gcc.dg/vect/vect-early-break_114-pr113750.c: New test.
>       * gcc.dg/vect/vect-early-break_115-pr113750.c: New test.
>       * gcc.dg/vect/vect-early-break_116-pr113750.c: New test.
> 
> --- inline copy of patch -- 
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..559ebd84d5c39881e694e7c8c31be29d846866ed
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> +
> +#ifndef N
> +#define N 800
> +#endif
> +unsigned vect_a[N];
> +unsigned vect_b[N];
> +
> +unsigned test4(unsigned x)
> +{
> + unsigned ret = 0;
> + for (int i = 0; i < N; i++)
> + {
> +   vect_b[i] = x + i;
> +   if (vect_a[i] != x)
> +     break;
> +foo:
> +   vect_a[i] = x;
> + }
> + return ret;
> +}
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..ba85780a46b1378aaec238ff9eb5f906be9a44dd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> +
> +#ifndef N
> +#define N 800
> +#endif
> +unsigned vect_a[N];
> +unsigned vect_b[N];
> +
> +unsigned test4(unsigned x)
> +{
> + unsigned ret = 0;
> + for (int i = 0; i < N; i++)
> + {
> +   vect_b[i] = x + i;
> +   if (vect_a[i] != x)
> +     break;
> +   vect_a[i] = x;
> +foo:
> + }
> + return ret;
> +}
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..37af2998688f5d60e2cdb372ab43afcaa52a3146
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> +
> +#ifndef N
> +#define N 800
> +#endif
> +unsigned vect_a[N];
> +unsigned vect_b[N];
> +
> +unsigned test4(unsigned x)
> +{
> + unsigned ret = 0;
> + for (int i = 0; i < N; i++)
> + {
> +   vect_b[i] = x + i;
> +foo:
> +   if (vect_a[i] != x)
> +     break;
> +   vect_a[i] = x;
> + }
> + return ret;
> +}
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..502686d308e298cd84e9e3b74d7b4ad1979602a9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> +
> +#ifndef N
> +#define N 800
> +#endif
> +unsigned vect_a[N];
> +unsigned vect_b[N];
> +
> +unsigned test4(unsigned x)
> +{
> + unsigned ret = 0;
> + for (int i = 0; i < N; i++)
> + {
> +foo:
> +   vect_b[i] = x + i;
> +   if (vect_a[i] != x)
> +     break;
> +   vect_a[i] = x;
> + }
> + return ret;
> +}
> diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c 
> b/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..4e02158aa351c8e1a5edf6cc7bcab0b5eaa06795
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c
> @@ -0,0 +1,26 @@
> +/* { dg-do compile } */
> +/* { dg-add-options vect_early_break } */
> +/* { dg-require-effective-target vect_early_break } */
> +/* { dg-require-effective-target vect_int } */
> +
> +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
> +
> +#ifndef N
> +#define N 800
> +#endif
> +unsigned vect_a[N];
> +unsigned vect_b[N];
> +
> +unsigned test4(unsigned x)
> +{
> + unsigned ret = 0;
> + for (int i = 0; i < N; i++)
> + {
> +   vect_b[i] = x + i;
> +   if (vect_a[i] != x)
> +foo:
> +     break;
> +   vect_a[i] = x;
> + }
> + return ret;
> +}
> diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
> index 
> 53fdfc25d7dc2deb7788176252697d2e455555fc..109d4ce5192f304d31f36fd6dfe32dd1f4bcbe82
>  100644
> --- a/gcc/tree-vect-data-refs.cc
> +++ b/gcc/tree-vect-data-refs.cc
> @@ -819,6 +819,18 @@ vect_analyze_early_break_dependences (loop_vec_info 
> loop_vinfo)
>       trapped already during loop form analysis.  */
>    gcc_assert (dest_bb->loop_father == loop);
>  
> +  /* Check that the destination block we picked has only one pred.  To relax 
> this we
> +     have to take special care when moving the statements.  We don't 
> currently support
> +     such control flow however this check is there to simplify how we handle
> +     labels that may be present anywhere in the IL.  This check is to ensure 
> that the
> +     labels aren't significant for the CFG.  */
> +  if (!single_pred (dest_bb))
> +    return opt_result::failure_at (vect_location,
> +                          "chosen loop exit block (BB %d) does not have a "
> +                          "single predecessor which is currently not "
> +                          "supported for early break vectorization.\n",
> +                          dest_bb->index);
> +
>    LOOP_VINFO_EARLY_BRK_DEST_BB (loop_vinfo) = dest_bb;
>  
>    if (!LOOP_VINFO_EARLY_BRK_VUSES (loop_vinfo).is_empty ())
> diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
> index 
> e2587315020a35a7d4ebd3e7a9842caa36bb5d3c..e85b1fd20eda815d5615c1934c2ac5afcaf53f67
>  100644
> --- a/gcc/tree-vect-loop.cc
> +++ b/gcc/tree-vect-loop.cc
> @@ -11786,7 +11786,7 @@ move_early_exit_stmts (loop_vec_info loop_vinfo)
>  
>    /* Move all stmts that need moving.  */
>    basic_block dest_bb = LOOP_VINFO_EARLY_BRK_DEST_BB (loop_vinfo);
> -  gimple_stmt_iterator dest_gsi = gsi_start_bb (dest_bb);
> +  gimple_stmt_iterator dest_gsi = gsi_after_labels (dest_bb);
>  
>    for (gimple *stmt : LOOP_VINFO_EARLY_BRK_STORES (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)

Reply via email to