Try to resolve paths in threader without looking further back.
authorAldy Hernandez <aldyh@redhat.com>
Wed, 20 Oct 2021 05:29:25 +0000 (07:29 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Tue, 26 Oct 2021 06:20:10 +0000 (08:20 +0200)
Sometimes we can solve a candidate path without having to recurse
further back.  This can mostly happen in fully resolving mode, because
we can ask the ranger what the range on entry to the path is, but
there's no reason this can't always apply.  This one-liner removes
the fully-resolving restriction.

I'm tickled pink to see how many things we now get quite early
in the compilation.  I actually had to disable jump threading entirely
for a few tests because the early threader was catching things
disturbingly early.  Also, as Richi predicted, I saw a lot of pre-VRP
cleanups happening.

I was going to commit this as obvious, but I think the test changes
merit discussion.

We've been playing games with gcc.dg/tree-ssa/ssa-thread-11.c for quite
some time.  Every time a threading pass gets smarter, we push the
check further down the pipeline.  We've officially run out of dumb
threading passes to disable ;-).  In the last year we've gone up from a
handful of threads, to 34 threads with the current combination of
options.  I doubt this is testing anything useful anymore, so I've
removed it.

Similarly for gcc.dg/tree-ssa/ssa-dom-thread-4.c.  We used to thread 3
jump threads, but they were disallowed because of loop rotation.  Then
we started catching more jump threads in VRP2 threading so we tested
there.  With this patch though, we triple the number of threads found
from 11 to 31.  I believe this test has outlived its usefulness, and
I've removed it.  Note that even though we have these outrageous
possibilities for this test, the block copier ultimately chops them
down (23 survive though).

Tested on x86-64 Linux.

gcc/ChangeLog:

* tree-ssa-threadbackward.c (back_threader::find_paths_to_names):
Always try to resolve path without looking back.
* tree-ssa-threadupdate.c (dump_jump_thread): Indidicate whether
edge is a back edge.

gcc/testsuite/ChangeLog:

* gcc.dg/graphite/scop-dsyr2k-2.c: Adjust for jump threading changes.
* gcc.dg/graphite/scop-dsyr2k.c: Same.
* gcc.dg/graphite/scop-dsyrk-2.c: Same.
* gcc.dg/graphite/scop-dsyrk.c: Same.
* gcc.dg/tree-ssa/pr20701.c: Same.
* gcc.dg/tree-ssa/pr20702.c: Same.
* gcc.dg/tree-ssa/pr21086.c: Same.
* gcc.dg/tree-ssa/pr25382.c: Same.
* gcc.dg/tree-ssa/pr58480.c: Same.
* gcc.dg/tree-ssa/ssa-vrp-thread-1.c: Same.
* gcc.dg/tree-ssa/vrp08.c: Same.
* gcc.dg/tree-ssa/vrp55.c: Same.
* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Same.
* gcc.dg/tree-ssa/ssa-dom-thread-4.c: Removed.
* gcc.dg/tree-ssa/ssa-thread-11.c: Removed.
* gcc.dg/uninit-pr89230-1.c: xfail.

19 files changed:
gcc/testsuite/gcc.dg/graphite/scop-dsyr2k-2.c
gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c
gcc/testsuite/gcc.dg/graphite/scop-dsyrk-2.c
gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c
gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
gcc/testsuite/gcc.dg/tree-ssa/pr20702.c
gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
gcc/testsuite/gcc.dg/tree-ssa/pr25382.c
gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c [deleted file]
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-11.c [deleted file]
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-backedge.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c
gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
gcc/testsuite/gcc.dg/tree-ssa/vrp55.c
gcc/testsuite/gcc.dg/uninit-pr89230-1.c
gcc/tree-ssa-threadbackward.c
gcc/tree-ssa-threadupdate.c

index 06aa19a..42e23fc 100644 (file)
@@ -1,4 +1,5 @@
 /* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fno-thread-jumps" } */
 #define NMAX 3000
 
 static double a[NMAX][NMAX], b[NMAX][NMAX], c[NMAX][NMAX];
index 41c91b9..feb9935 100644 (file)
@@ -1,4 +1,5 @@
 /* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fno-thread-jumps" } */
 #define NMAX 3000
 
 static double a[NMAX][NMAX], b[NMAX][NMAX], c[NMAX][NMAX];
index 5622dce..935ade3 100644 (file)
@@ -1,4 +1,5 @@
 /* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fno-thread-jumps" } */
 #define NMAX 3000
 #define MEASURE_TIME 1
 
index e01a517..5c65e40 100644 (file)
@@ -1,4 +1,5 @@
 /* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fno-thread-jumps" } */
 #define NMAX 3000
 #define MEASURE_TIME 1
 
index 2f91458..496c425 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fdelete-null-pointer-checks -fdisable-tree-thread1" } */
 
 typedef struct {
   int code;
index c896857..8112967 100644 (file)
@@ -4,7 +4,7 @@
    immediate successors of the basic block.  */
 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-dominator-opts -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-thread-jumps -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
 
 extern void bar (int);
 
index aadd53e..9b93d39 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-thread-jumps -fdisable-tree-evrp -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */
 
 int
 foo (int *p)
index d747655..8634c0a 100644 (file)
@@ -3,7 +3,7 @@
    Check that VRP now gets ranges from BIT_AND_EXPRs.  */
 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-ccp -fdisable-tree-evrp -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fno-thread-jumps -fno-tree-ccp -fdisable-tree-evrp -fdump-tree-vrp1" } */
 
 int
 foo (int a)
index 42898e7..f11623b 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
-/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-thread-jumps -fdisable-tree-evrp -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
 
 extern void eliminate (void);
 extern void* f1 (void *a, void *b) __attribute__((nonnull));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c
deleted file mode 100644 (file)
index 9cd4635..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/* { dg-do compile } */ 
-/* { dg-options "-O2 -fdump-tree-vrp-thread2-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */
-struct bitmap_head_def;
-typedef struct bitmap_head_def *bitmap;
-typedef const struct bitmap_head_def *const_bitmap;
-typedef unsigned long BITMAP_WORD;
-typedef struct bitmap_element_def
-{
-  struct bitmap_element_def *next;
-  unsigned int indx;
-} bitmap_element;
-
-
-
-
-
-
-
-
-
-unsigned char
-bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
-                     const_bitmap kill)
-{
-  unsigned char changed = 0;
-
-  bitmap_element *dst_elt;
-  const bitmap_element *a_elt, *b_elt, *kill_elt, *dst_prev;
-
-  while (a_elt || b_elt)
-    {
-      unsigned char new_element = 0;
-
-      if (b_elt)
-       while (kill_elt && kill_elt->indx < b_elt->indx)
-         kill_elt = kill_elt->next;
-
-      if (b_elt && kill_elt && kill_elt->indx == b_elt->indx
-         && (!a_elt || a_elt->indx >= b_elt->indx))
-       {
-         bitmap_element tmp_elt;
-         unsigned ix;
-
-         BITMAP_WORD ior = 0;
-
-             changed = bitmap_elt_ior (dst, dst_elt, dst_prev,
-                                       a_elt, &tmp_elt, changed);
-
-       }
-
-    }
-
-
-  return changed;
-}
-/* We used to catch 3 jump threads in vrp-thread1, but they all
-   rotated the loop, so they were disallowed.  This in turn created
-   other opportunities for the other threaders which result in the the
-   post-loop threader (vrp-thread2) catching more.  */
-/* { dg-final { scan-tree-dump-times "Registering jump thread" 5 "vrp-thread2" } } */
index 1da00a6..ed252b9 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */
 
-/* { dg-final { scan-tree-dump "Jumps threaded: 12"  "thread3" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 11" "thread3" } } */
 /* { dg-final { scan-tree-dump-not "Jumps threaded"  "dom2" } } */
 
 /* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC.  It's high enough
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-11.c
deleted file mode 100644 (file)
index 672a54e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp2-details --param logical-op-non-short-circuit=1" } */
-/* { dg-additional-options "-fdisable-tree-ethread -fdisable-tree-thread1 -fdisable-tree-thread2" } */
-/* { dg-final { scan-tree-dump-not "IRREDUCIBLE_LOOP" "vrp2" } } */
-
-void abort (void);
-typedef struct bitmap_head_def *bitmap;
-typedef const struct bitmap_head_def *const_bitmap;
-typedef struct bitmap_obstack
-{
-  struct bitmap_obstack *next;
-  unsigned int indx;
-}
-bitmap_element;
-typedef struct bitmap_head_def
-{
-  bitmap_element *first;
-}
-bitmap_head;
-static __inline__ unsigned char
-bitmap_elt_ior (bitmap dst, bitmap_element * dst_elt,
-               bitmap_element * dst_prev, const bitmap_element * a_elt,
-               const bitmap_element * b_elt)
-{
-  ((void) (!(a_elt || b_elt) ? abort (), 0 : 0));
-}
-
-unsigned char
-bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b,
-                     const_bitmap kill)
-{
-  bitmap_element *dst_elt = dst->first;
-  const bitmap_element *a_elt = a->first;
-  const bitmap_element *b_elt = b->first;
-  const bitmap_element *kill_elt = kill->first;
-  bitmap_element *dst_prev = ((void *) 0);
-  while (a_elt || b_elt)
-    {
-      if (b_elt && kill_elt && kill_elt->indx == b_elt->indx
-         && (!a_elt || a_elt->indx >= b_elt->indx));
-      else
-       {
-         bitmap_elt_ior (dst, dst_elt, dst_prev, a_elt, b_elt);
-         if (a_elt && b_elt && a_elt->indx == b_elt->indx)
-           ;
-         else if (a_elt && (!b_elt || a_elt->indx <= b_elt->indx))
-           a_elt = a_elt->next;
-       }
-    }
-}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-backedge.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-backedge.c
new file mode 100644 (file)
index 0000000..890a0ee
--- /dev/null
@@ -0,0 +1,32 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdisable-tree-ethread -fdisable-tree-thread1 -fdisable-tree-thread2 -fno-tree-dominator-opts -fdump-tree-thread3-details" }
+
+// Test that we can thread jumps across the backedge of a loop through
+// the switch statement to a particular case.
+//
+// Just in case, we disable all the jump threaders before loop
+// optimizations to make sure we get a clean stab at this.
+
+int foo (unsigned int x, int s)
+{
+  while (s != 999)
+    {
+      switch (s)
+       {
+       case 0:
+         if (x)
+           s = 1;
+         break;
+       case 1:
+         if (x)
+           s = 999;
+         break;
+       default:
+         break;
+       }
+      x++;
+    }
+  return s;
+}
+
+// { dg-final { scan-tree-dump "Registering jump thread:.*normal \\(back\\)" "thread3" } }
index 86d07ef..f3ca140 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-thread1-details -fdelete-null-pointer-checks" } */
 /* { dg-skip-if "" keeps_null_pointer_checks } */
 
 void oof (void);
@@ -29,5 +29,5 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent,
 
 /* ARM Cortex-M defined LOGICAL_OP_NON_SHORT_CIRCUIT to false,
    so skip below test.  */
-/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp-thread1" { target { ! arm_cortex_m } } } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 1 "thread1" { target { ! arm_cortex_m } } } } */
 
index c2da30b..2c6742b 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-fre -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-tree-fre -fdisable-tree-evrp -fdump-tree-vrp1-details -fdisable-tree-thread1 -fdelete-null-pointer-checks" } */
 
 /* Compile with -fno-tree-fre -O2 to prevent CSEing *p.  */
 int
index a478a69..0ef57d9 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp-thread1-blocks-vops-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdump-tree-ethread-details -fdelete-null-pointer-checks" } */
 
 void arf (void);
 
@@ -12,6 +12,6 @@ fu (char *p, int x)
     arf ();
 }
 
-/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" { target { ! keeps_null_pointer_checks } } } } */
-/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp-thread1" { target {   keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 1 "ethread" { target { ! keeps_null_pointer_checks } } } } */
+/* { dg-final { scan-tree-dump-times "Registering jump thread" 0 "ethread" { target {   keeps_null_pointer_checks } } } } */
 
index 1c07c4f..dfc87a5 100644 (file)
@@ -8,7 +8,8 @@ struct S { int i, j; };
 
 int g (void)
 {
-  struct S *p = f (), *q;
+  struct S *p = f ();
+  struct S *q; // { dg-bogus "may be used uninitialized" "uninitialized" { xfail *-*-* } }
 
   if (p->i || !(q = f ()) || p->j != q->i)
    {
index d94e3b9..edb396b 100644 (file)
@@ -374,8 +374,8 @@ back_threader::find_paths_to_names (basic_block bb, bitmap interesting)
       return false;
     }
 
-  // Try to resolve the path with nothing but ranger knowledge.
-  if (m_resolve && m_path.length () > 1 && maybe_register_path ())
+  // Try to resolve the path without looking back.
+  if (m_path.length () > 1 && maybe_register_path ())
     {
       m_path.pop ();
       m_visited_bbs.remove (bb);
index 8e6f043..8aac733 100644 (file)
@@ -253,6 +253,9 @@ dump_jump_thread_path (FILE *dump_file,
        default:
          gcc_unreachable ();
        }
+
+      if ((path[i]->e->flags & EDGE_DFS_BACK) != 0)
+       fprintf (dump_file, " (back)");
     }
   fprintf (dump_file, "; \n");
 }