re PR middle-end/36550 (Wrong "may be used uninitialized" warning (conditional PHIs))
authorJeff Law <law@redhat.com>
Fri, 15 Dec 2017 22:35:51 +0000 (15:35 -0700)
committerJeff Law <law@gcc.gnu.org>
Fri, 15 Dec 2017 22:35:51 +0000 (15:35 -0700)
PR tree-optimization/36550
* tree-ssa-threadupdate.c (count_stmts_and_phis_in_block): New.
(mark_threaded_blocks): Rewrite code to avoid block copying when
optimizing for size.  Don't pessimize blocks which will be
copied, but all the statements will be dead.

PR tree-optimization/36550
* gcc.dg/tree-ssa/pr36550.c: New test.

From-SVN: r255731

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr36550.c [new file with mode: 0644]
gcc/tree-ssa-threadupdate.c

index e5ab1b1a4c788ecf3a379239026edff457473e96..4528b6db5f2e6ff854826c2f7474f4470b67f5e2 100644 (file)
@@ -1,3 +1,11 @@
+2017-12-15  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/36550
+       * tree-ssa-threadupdate.c (count_stmts_and_phis_in_block): New.
+       (mark_threaded_blocks): Rewrite code to avoid block copying when
+       optimizing for size.  Don't pessimize blocks which will be
+       copied, but all the statements will be dead.
+
 2017-12-15  Alexandre Oliva <aoliva@redhat.com>
 
        PR tree-optimization/81165
index bc005b8de26a593245558d67d3ba95eaff9413a1..5c91661c71b0e8775541b6845140dbf2d83081d8 100644 (file)
@@ -1,3 +1,8 @@
+2017-12-15  Jeff Law  <law@redhat.com>
+
+       PR tree-optimization/36550
+       * gcc.dg/tree-ssa/pr36550.c: New test.
+
 2017-12-15  Alexandre Oliva  <aoliva@redhat.com>
 
        PR tree-optimization/81165
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36550.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36550.c
new file mode 100644 (file)
index 0000000..3eda508
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -Wuninitialized" } */
+void bail(void) __attribute__((noreturn));
+unsigned once(void);
+int pr(char**argv)
+{
+       char *bug;
+       unsigned check = once();
+       if (check) {
+               if (*argv)
+                       bug = *++argv;
+       } else {
+               bug = *argv++;
+               if (!*argv)
+                       bail();
+       }
+       /* now bug is set except if (check && !*argv) */
+       if (check) {
+               if (!*argv)
+                       return 0;
+       }
+       /* if we ever get here then bug is set */
+       return *bug != 'X';
+}
+
index b29ffe195c8dd105123266f02d1445b3f514aea6..7b823d130fac7519d6f264d3065bc1f0d269f7b7 100644 (file)
@@ -1737,6 +1737,31 @@ phi_args_equal_on_edges (edge e1, edge e2)
   return true;
 }
 
+/* Return the number of non-debug statements and non-virtual PHIs in a
+   block.  */
+
+static unsigned int
+count_stmts_and_phis_in_block (basic_block bb)
+{
+  unsigned int num_stmts = 0;
+
+  gphi_iterator gpi;
+  for (gpi = gsi_start_phis (bb); !gsi_end_p (gpi); gsi_next (&gpi))
+    if (!virtual_operand_p (PHI_RESULT (gpi.phi ())))
+      num_stmts++;
+
+  gimple_stmt_iterator gsi;
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple *stmt = gsi_stmt (gsi);
+      if (!is_gimple_debug (stmt))
+        num_stmts++;
+    }
+
+  return num_stmts;
+}
+
+
 /* Walk through the registered jump threads and convert them into a
    form convenient for this pass.
 
@@ -1856,28 +1881,51 @@ mark_threaded_blocks (bitmap threaded_blocks)
        }
     }
 
-  /* If optimizing for size, only thread through block if we don't have
-     to duplicate it or it's an otherwise empty redirection block.  */
+  /* When optimizing for size, prune all thread paths where statement
+     duplication is necessary.
+
+     We walk the jump thread path looking for copied blocks.  There's
+     two types of copied blocks.
+
+       EDGE_COPY_SRC_JOINER_BLOCK is always copied and thus we will
+       cancel the jump threading request when optimizing for size.
+
+       EDGE_COPY_SRC_BLOCK which is copied, but some of its statements
+       will be killed by threading.  If threading does not kill all of
+       its statements, then we should cancel the jump threading request
+       when optimizing for size.  */
   if (optimize_function_for_size_p (cfun))
     {
       EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
        {
-         bb = BASIC_BLOCK_FOR_FN (cfun, i);
-         if (EDGE_COUNT (bb->preds) > 1
-             && !redirection_block_p (bb))
-           {
-             FOR_EACH_EDGE (e, ei, bb->preds)
-               {
-                 if (e->aux)
-                   {
-                     vec<jump_thread_edge *> *path = THREAD_PATH (e);
-                     delete_jump_thread_path (path);
-                     e->aux = NULL;
-                   }
-               }
-           }
-         else
-           bitmap_set_bit (threaded_blocks, i);
+         FOR_EACH_EDGE (e, ei, BASIC_BLOCK_FOR_FN (cfun, i)->preds)
+           if (e->aux)
+             {
+               vec<jump_thread_edge *> *path = THREAD_PATH (e);
+
+               unsigned int j;
+               for (j = 1; j < path->length (); j++)
+                 {
+                   bb = (*path)[j]->e->src;
+                   if (redirection_block_p (bb))
+                     ;
+                   else if ((*path)[j]->type == EDGE_COPY_SRC_JOINER_BLOCK
+                            || ((*path)[j]->type == EDGE_COPY_SRC_BLOCK
+                                && (count_stmts_and_phis_in_block (bb)
+                                    != estimate_threading_killed_stmts (bb))))
+                     break;
+                 }
+
+               if (j != path->length ())
+                 {
+                   if (dump_file && (dump_flags & TDF_DETAILS))
+                     dump_jump_thread_path (dump_file, *path, 0);
+                   delete_jump_thread_path (path);
+                   e->aux = NULL;
+                 }
+               else
+                 bitmap_set_bit (threaded_blocks, i);
+             }
        }
     }
   else