This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] [RFA] [PR tree-optmization/69740] Schedule loop fixups when needed


On Thu, Feb 25, 2016 at 7:18 AM, Jeff Law <law@redhat.com> wrote:
>
> PR69740 shows two instances where one or more transformations ultimately
> lead to the removal of a basic block.
>
> In both cases, removal of the basic block removes a path into an irreducible
> region and turns the irreducible region into a natural loop.
>
> When that occurs we need to be requesting loops to be fixed up.
>
> My first patch was to handle this is was in tree-ssa-dce.c and that fixed
> the initial problem report.  As I was cobbling the patch together, I
> pondered putting the changes into delete_basic_block because that would
> capture other instances of this problem.
>
> When I looked at the second instance, it came via a completely different
> path (tail merging).  Again it was a case where we called delete_basic_block
> which in turn changed an irreducible region into a natural loop.  So I
> tossed my original patch and put the test into delete_basic_block as you see
> here.
>
> Bootstrapped and regression tested on x86_64-linux-gnu.  OK for the trunk
> and the gcc-5 branch after a suitable soak time?
>
>
>
> Jeff
>
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index 913abc8..42e5b4f 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,10 @@
> +2016-02-24  Jeff Law  <law@redhat.com>
> +
> +       PR tree-optimization/69740
> +       * cfghooks.c (delete_basic_block): Request loop fixups if we delete
> +       a block with an outgoing edge to a block marked as being in anx
> +       irreducible region.
> +
>  2016-02-24  Jason Merrill  <jason@redhat.com>
>
>         * common.opt (flifetime-dse): Add -flifetime-dse=1.
> diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
> index bbb1017..4d31aa9 100644
> --- a/gcc/cfghooks.c
> +++ b/gcc/cfghooks.c
> @@ -574,6 +574,14 @@ delete_basic_block (basic_block bb)
>    if (!cfg_hooks->delete_basic_block)
>      internal_error ("%s does not support delete_basic_block",
> cfg_hooks->name);
>
> +  /* Look at BB's successors, if any are marked as BB_IRREDUCIBLE_LOOP,
> then
> +     removing BB (and its outgoing edges) may make the loop a natural
> +     loop.  In which case we need to schedule loop fixups.  */
> +  if (current_loops)
> +    for (edge_iterator ei = ei_start (bb->succs); !ei_end_p (ei); ei_next
> (&ei))
> +      if (ei_edge (ei)->dest->flags & BB_IRREDUCIBLE_LOOP)
> +       loops_state_set (LOOPS_NEED_FIXUP);

So I fail to see how only successor edges are relevant.  Isn't the important
case to catch whether we remove an edge marked EDGE_IRREDUCIBLE_LOOP?
Even if the BB persists we might have exposed a new loop here.

Note that it is not safe to look at {BB,EDGE}_IRREDUCIBLE_LOOP if the loop
state does not have LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS set
(the flags may be stale or missing).  So it might be that we can't rely on
non-loop passes modifying the CFG to handle this optimistically.

Thus, how about (my main point) moving this to remove_edge instead, like

Index: gcc/cfghooks.c
===================================================================
--- gcc/cfghooks.c      (revision 233693)
+++ gcc/cfghooks.c      (working copy)
@@ -408,7 +408,15 @@ void
 remove_edge (edge e)
 {
   if (current_loops != NULL)
-    rescan_loop_exit (e, false, true);
+    {
+      rescan_loop_exit (e, false, true);
+      /* If we remove an edge that is part of an irreducible region
+         or we remove an entry into an irreducible region we may expose
+        new natural loops.  */
+      if (e->flags & EDGE_IRREDUCIBLE_LOOP
+         || e->dest->flags & BB_IRREDUCIBLE_LOOP)
+       loops_state_set (LOOPS_NEED_FIXUP);
+    }

   /* This is probably not needed, but it doesn't hurt.  */
   /* FIXME: This should be called via a remove_edge hook.  */

that then handles delete_basic_block via its call to remove all
incoming/outgoing edges.

As for the comment above it may need to be conservatively

   if (! loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
      || checks above)

That looks like a more complete fix (and it avoids an extra loop over
all edges).

(the edge flag check might be redundant given it's only set if both
src and dest are
BB_IRREDUCIBLE_LOOP).

Richard.

>    cfg_hooks->delete_basic_block (bb);
>
>    if (current_loops != NULL)
> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
> index 311232f..b0df819 100644
> --- a/gcc/testsuite/ChangeLog
> +++ b/gcc/testsuite/ChangeLog
> @@ -1,3 +1,9 @@
> +2016-02-04  Jeff Law  <law@redhat.com>
> +
> +       PR tree-optimization/69740
> +       * gcc.c-torture/compile/pr69740-1.c: New test.
> +       * gcc.c-torture/compile/pr69740-2.c: New test.
> +
>  2016-02-24  Martin Sebor  <msebor@redhat.com>
>
>         PR c++/69912
> diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c
> b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c
> new file mode 100644
> index 0000000..ac867d8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-1.c
> @@ -0,0 +1,12 @@
> +char a;
> +short b;
> +void fn1() {
> +  if (b)
> +    ;
> +  else {
> +    int c[1] = {0};
> +  l1:;
> +  }
> +  if (a)
> +    goto l1;
> +}
> diff --git a/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c
> b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c
> new file mode 100644
> index 0000000..a89c9a0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.c-torture/compile/pr69740-2.c
> @@ -0,0 +1,19 @@
> +inline int foo(int *p1, int p2) {
> +  int z = *p1;
> +  while (z > p2)
> +    p2 = 2;
> +  return z;
> +}
> +int main() {
> +  int i;
> +  for (;;) {
> +    int j, k;
> +    i = foo(&k, 7);
> +    if (k)
> +      j = i;
> +    else
> +      k = j;
> +    if (2 != j)
> +      __builtin_abort();
> +  }
> +}
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]