> Am 04.12.2024 um 06:24 schrieb Andrew Pinski <quic_apin...@quicinc.com>:
>
> After r12-5300-gf98f373dd822b3, phiopt could get the following bb structure:
> |
> middle-bb -----|
> | |
> | |----| |
> phi<1, 2> | |
> cond | |
> | | |
> |--------+---|
>
> Which was considered 2 loops. The inner loop had esimtate of upper_bound to
> be 8,
> due to the original `for (b = 0; b <= 7; b++)`. The outer loop was already an
> infinite one.
> So phiopt would come along and change the condition to be unconditionally
> true,
> we change the inner loop to being an infinite one but don't reset the estimate
> on the loop and cleanup cfg comes along and changes it into one loop but also
> does not reset the estimate of the loop. Then the loop unrolling uses the old
> estimate
> and decides to add an unreachable there.o
> So the fix is when phiopt changes an exit to a loop, reset the estimates,
> similar to
> how cleanupcfg does it when merging some basic blocks.
>
> Bootstrapped and tested on x86_64-linux-gnu.
Ok
Richard
> PR tree-optimization/117243
> PR tree-optimization/116749
>
> gcc/ChangeLog:
>
> * tree-ssa-phiopt.cc (replace_phi_edge_with_variable): Reset loop
> estimates if the cond_block was an exit to a loop.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/torture/pr117243-1.c: New test.
> * gcc.dg/torture/pr117243-2.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
> gcc/testsuite/gcc.dg/torture/pr117243-1.c | 30 ++++++++++++++++++++
> gcc/testsuite/gcc.dg/torture/pr117243-2.c | 34 +++++++++++++++++++++++
> gcc/tree-ssa-phiopt.cc | 11 ++++++++
> 3 files changed, 75 insertions(+)
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-1.c
> create mode 100644 gcc/testsuite/gcc.dg/torture/pr117243-2.c
>
> diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-1.c
> b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
> new file mode 100644
> index 00000000000..c4bbc31467c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr117243-1.c
> @@ -0,0 +1,30 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fdump-tree-optimized" } */
> +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
> +
> +/* PR tree-optimization/117243 */
> +/* foo should be an infinite but sometimes it gets optimized incorrectly into
> + an __builtin_unreachable(); which is not valid. */
> +void
> +foo (unsigned int a, unsigned char b)
> +{
> + lbl:
> + for (b = 0; b <= 7; b++)
> + {
> + unsigned char c[1][1];
> + int i, j;
> + for (i = 0; i < 1; i++)
> + for (j = 0; j < 1; j++)
> + c[i][j] = 1;
> + if (b)
> + goto lbl;
> + }
> +}
> +
> +int
> +main ()
> +{
> + foo (1, 2);
> +}
> +
> +/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
> diff --git a/gcc/testsuite/gcc.dg/torture/pr117243-2.c
> b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
> new file mode 100644
> index 00000000000..d9b0d3eeb98
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr117243-2.c
> @@ -0,0 +1,34 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fno-tree-ch -fdump-tree-optimized" } */
> +/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } { "" } } */
> +
> +/* PR tree-optimization/117243 */
> +/* PR tree-optimization/116749 */
> +
> +/* main1 should be an infinite but sometimes it gets optimized incorrectly
> into
> + an __builtin_unreachable(); which is not valid. */
> +int main1 (void)
> +{
> + int g=0;
> + int l1[1];
> + int *l2 = &g;
> + int i;
> + for (i=0; i<1; i++)
> + l1[i] = (1);
> + for (g=0; g; ++g)
> + {
> + int *l3[1] = {&l1[0]};
> + }
> + *l2 = *l1;
> +b:
> + for (i=0; i<2; ++i)
> + {
> + if (i)
> + goto b;
> + if (g)
> + continue;
> + }
> + return 0;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "__builtin_unreachable " "optimized"} } */
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index 15651809d71..d7b7c7467c1 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
> #include "tree-ssa-propagate.h"
> #include "tree-ssa-dce.h"
> #include "calls.h"
> +#include "tree-ssa-loop-niter.h"
>
> /* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */
>
> @@ -152,6 +153,16 @@ replace_phi_edge_with_variable (basic_block cond_block,
> else
> gcc_unreachable ();
>
> + /* If we are removing the cond on a loop exit,
> + reset number of iteration information of the loop. */
> + if (loop_exits_from_bb_p (cond_block->loop_father, cond_block))
> + {
> + auto loop = cond_block->loop_father;
> + free_numbers_of_iterations_estimates (loop);
> + loop->any_upper_bound = false;
> + loop->any_likely_upper_bound = false;
> + }
> +
> if (edge_to_remove && EDGE_COUNT (edge_to_remove->dest->preds) == 1)
> {
> e->flags |= EDGE_FALLTHRU;
> --
> 2.43.0
>