re PR libstdc++/85116 (std::min_element does not optimize well with inlined predicate)
authorRichard Biener <rguenther@suse.de>
Thu, 26 Apr 2018 12:18:58 +0000 (12:18 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 26 Apr 2018 12:18:58 +0000 (12:18 +0000)
2018-04-26  Richard Biener  <rguenther@suse.de>

PR tree-optimization/85116
* tree-ssa-loop-ch.c (do_while_loop_p): A do-while loop should
have a loop exit from the single latch predecessor.  Remove
case of header with just condition.
(ch_base::copy_headers): Exclude infinite loops from any
processing.
(pass_ch::execute): Record exits.

* gcc.dg/tree-ssa/copy-headers-2.c: New testcase.
* gcc.dg/tree-ssa/copy-headers-3.c: Likewise.
* gcc.dg/tree-ssa/copy-headers-4.c: Likewise.
* gcc.dg/tree-ssa/loadpre6.c: Adjust.

From-SVN: r259672

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c
gcc/tree-ssa-loop-ch.c

index 61324440b068e79b2acd84cb84654791cbeff91d..2fed948fd220a3e942f1dba72a21dd4ac880a254 100644 (file)
@@ -1,3 +1,13 @@
+2018-04-26  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/85116
+       * tree-ssa-loop-ch.c (do_while_loop_p): A do-while loop should
+       have a loop exit from the single latch predecessor.  Remove
+       case of header with just condition.
+       (ch_base::copy_headers): Exclude infinite loops from any
+       processing.
+       (pass_ch::execute): Record exits.
+
 2018-04-26  Richard Biener  <rguenther@suse.de>
 
        * tree-vect-data-refs.c (vect_get_data_access_cost): Get
index a62a9cb86f4da91f0aa4e06daf8d46c28b6eca08..a4d32ec2574ceb3a63d9a1c92c7f0215120652ce 100644 (file)
@@ -1,3 +1,11 @@
+2018-04-26  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/85116
+       * gcc.dg/tree-ssa/copy-headers-2.c: New testcase.
+       * gcc.dg/tree-ssa/copy-headers-3.c: Likewise.
+       * gcc.dg/tree-ssa/copy-headers-4.c: Likewise.
+       * gcc.dg/tree-ssa/loadpre6.c: Adjust.
+
 2018-04-25  Sebastian Peryt  <sebastian.peryt@intel.com>
 
        PR target/85473
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-2.c
new file mode 100644 (file)
index 0000000..7f1bfe1
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ch2-details" } */
+
+int *a, *b;
+int test(int n, int k)
+{
+  int it = 0;
+  while (++it < n)
+    {
+      if (it % k == 1)
+       a[it] = 0;
+      else
+       b[it] = 1;
+    }
+}
+
+/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-3.c
new file mode 100644 (file)
index 0000000..6b63cdf
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-ch2-details" } */
+
+int __GIMPLE (startwith("ch"))
+test2 (int n)
+{
+bb_3:
+  if (n_1(D) > 0)
+    goto bb_3;
+  else
+    goto bb_4;
+
+bb_4:
+  return;
+
+}
+
+/* { dg-final { scan-tree-dump "is do-while loop" "ch2" } } */
+/* { dg-final { scan-tree-dump-not "is not do-while loop" "ch2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-4.c
new file mode 100644 (file)
index 0000000..88466c6
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ch2-details" } */
+
+int *a, *b;
+int test(int n, int k)
+{
+  int it = 0;
+  do
+    {
+      if (it % k == 1)
+       a[it] = 0;
+      else
+       b[it] = 1;
+    }
+  while (++it < n);
+}
+
+/* { dg-final { scan-tree-dump-not "is not do-while loop" "ch2" } } */
index 22248910086c3a795f272d0f001b5090e1eb43f7..028becdc6e3015ec14b53d4547f5aac154c5ba82 100644 (file)
@@ -75,4 +75,4 @@ main (void)
 
 /* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre1" } } */
 /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */
-/* { dg-final { scan-tree-dump-times "Insertions: 2" 1 "pre" } } */
+/* { dg-final { scan-tree-dump-times "Insertions: 1" 1 "pre" } } */
index 488999dd8ce3c17bbc54a78e5156e47b5e3de7cd..6b5c82c50a716912281c66ccdaf26c21396fa1b8 100644 (file)
@@ -165,17 +165,28 @@ do_while_loop_p (struct loop *loop)
       return false;
     }
 
-  /* If the header contains just a condition, it is not a do-while loop.  */
-  stmt = last_and_only_stmt (loop->header);
-  if (stmt
-      && gimple_code (stmt) == GIMPLE_COND)
+  /* If the latch does not have a single predecessor, it is not a
+     do-while loop.  */
+  if (!single_pred_p (loop->latch))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file,
+                "Loop %i is not do-while loop: latch has multiple "
+                "predecessors.\n", loop->num);
+      return false;
+    }
+
+  /* If the latch predecessor doesn't exit the loop, it is not a
+     do-while loop.  */
+  if (!loop_exits_from_bb_p (loop, single_pred (loop->latch)))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
-                "Loop %i is not do-while loop: "
-                "header contains just condition.\n", loop->num);
+                "Loop %i is not do-while loop: latch predecessor "
+                "does not exit loop.\n", loop->num);
       return false;
     }
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "Loop %i is do-while loop\n", loop->num);
 
@@ -305,8 +316,9 @@ ch_base::copy_headers (function *fun)
       /* If the loop is already a do-while style one (either because it was
         written as such, or because jump threading transformed it into one),
         we might be in fact peeling the first iteration of the loop.  This
-        in general is not a good idea.  */
-      if (!process_loop_p (loop))
+        in general is not a good idea.  Also avoid touching infinite loops.  */
+      if (!loop_has_exit_edges (loop)
+         || !process_loop_p (loop))
        continue;
 
       /* Iterate the header copying up to limit; this takes care of the cases
@@ -392,6 +404,15 @@ ch_base::copy_headers (function *fun)
       split_edge (loop_preheader_edge (loop));
       split_edge (loop_latch_edge (loop));
 
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         if (do_while_loop_p (loop))
+           fprintf (dump_file, "Loop %d is now do-while loop.\n", loop->num);
+         else
+           fprintf (dump_file, "Loop %d is still not do-while loop.\n",
+                    loop->num);
+       }
+
       changed = true;
     }
 
@@ -409,7 +430,8 @@ unsigned int
 pass_ch::execute (function *fun)
 {
   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
-                      | LOOPS_HAVE_SIMPLE_LATCHES);
+                      | LOOPS_HAVE_SIMPLE_LATCHES
+                      | LOOPS_HAVE_RECORDED_EXITS);
 
   unsigned int res = copy_headers (fun);