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 and cleanup cfg would remove the condition and remove the outer loop but not update the inner one becoming an infinite loop. I decided it was easier to avoid this inside phiopt rather than figuring out how to fix up cleanup cfg. This patch avoids the issue by rejecting edges back to the condition bb before loop optmiizations have been run. Bootstrapped and tested on x86_64-linux-gnu. Note since the testcases depend on the loop being infinite, I used the alarm signal trick. PR tree-optimization/117243 PR tree-optimization/116749 gcc/ChangeLog: * tree-ssa-phiopt.cc (execute_over_cond_phis): Reject edges back to the conditional bb before loop optimizers have been run. 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 | 44 ++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr117243-2.c | 54 +++++++++++++++++++++++ gcc/tree-ssa-phiopt.cc | 7 +++ 3 files changed, 105 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..46723132553 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr117243-1.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-require-effective-target signal } */ + +/* PR tree-optimization/117243 */ +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> + +void do_exit (int i) +{ + exit (0); +} + +/* 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 () +{ + struct sigaction s; + sigemptyset (&s.sa_mask); + s.sa_handler = do_exit; + s.sa_flags = 0; + sigaction (SIGALRM, &s, NULL); + alarm (1); + + foo (1, 2); +} + 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..5cb864b467d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr117243-2.c @@ -0,0 +1,54 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fno-tree-ch" } */ +/* { dg-require-effective-target signal } */ + +/* PR tree-optimization/117243 */ +/* PR tree-optimization/116749 */ +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> + +void do_exit (int i) +{ + exit (0); +} + +/* 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; +} + +int +main (void) +{ + struct sigaction s; + sigemptyset (&s.sa_mask); + s.sa_handler = do_exit; + s.sa_flags = 0; + sigaction (SIGALRM, &s, NULL); + alarm (1); + + main1 (); +} + diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 15651809d71..a2649590d29 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -4178,6 +4178,13 @@ execute_over_cond_phis (func_type func) e2 = EDGE_SUCC (bb, 1); bb2 = e2->dest; + /* If loop opts are not done, then don't handle a loop back to itself. + The loop estimates sometimes are not updated correctly when changing + a loop into an infinite loop. */ + if (!(cfun->curr_properties & PROP_loop_opts_done) + && (bb1 == bb || bb2 == bb)) + continue; + /* We cannot do the optimization on abnormal edges. */ if ((e1->flags & EDGE_ABNORMAL) != 0 || (e2->flags & EDGE_ABNORMAL) != 0) -- 2.43.0