gimple.h (stmt_can_terminate_bb_p): New function.
authorJan Hubicka <hubicka@ucw.cz>
Thu, 14 Jul 2016 13:52:21 +0000 (15:52 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 14 Jul 2016 13:52:21 +0000 (13:52 +0000)
* gimple.h (stmt_can_terminate_bb_p): New function.
* tree-cfg.c (need_fake_edge_p): Rename to ...
(stmt_can_terminate_bb_p): ... this; return true if stmt can
throw external; handle const and pure calls.
* tree-ssa-loop-niter.c (loop_only_exit_p): Use it.

From-SVN: r238336

gcc/ChangeLog
gcc/gimple.h
gcc/tree-cfg.c
gcc/tree-ssa-loop-niter.c

index 24b929812b64c1ef7bb122d641005e7d4b20feab..5830663300f04c3b5417658211b1ca35e0b531eb 100644 (file)
@@ -1,3 +1,11 @@
+2016-07-14  Jan Hubicka  <hubicka@ucw.cz>
+
+       * gimple.h (stmt_can_terminate_bb_p): New function.
+       * tree-cfg.c (need_fake_edge_p): Rename to ...
+       (stmt_can_terminate_bb_p): ... this; return true if stmt can
+       throw external; handle const and pure calls.
+       * tree-ssa-loop-niter.c (loop_only_exit_p): Use it.
+
 2016-07-14  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/71866
index 1da719c52e074be2daa6ceff1e8e2af93b96e0c7..980bdf8314c4481e979178d5a23688dd31d5d966 100644 (file)
@@ -1526,6 +1526,7 @@ extern void gimple_seq_set_location (gimple_seq, location_t);
 extern void gimple_seq_discard (gimple_seq);
 extern void maybe_remove_unused_call_args (struct function *, gimple *);
 extern bool gimple_inexpensive_call_p (gcall *);
+extern bool stmt_can_terminate_bb_p (gimple *);
 
 /* Formal (expression) temporary table handling: multiple occurrences of
    the same scalar expression are evaluated into the same temporary.  */
index 6d6943503fe911a7e43ae9ab86776cf7a23b4f2c..07280202ba34de394e511a5cca84034b53902597 100644 (file)
@@ -7919,15 +7919,20 @@ gimple_block_ends_with_condjump_p (const_basic_block bb)
 }
 
 
-/* Return true if we need to add fake edge to exit at statement T.
-   Helper function for gimple_flow_call_edges_add.  */
+/* Return true if statement T may terminate execution of BB in ways not
+   explicitly represtented in the CFG.  */
 
-static bool
-need_fake_edge_p (gimple *t)
+bool
+stmt_can_terminate_bb_p (gimple *t)
 {
   tree fndecl = NULL_TREE;
   int call_flags = 0;
 
+  /* Eh exception not handled internally terminates execution of the whole
+     function.  */
+  if (stmt_can_throw_external (t))
+    return true;
+
   /* NORETURN and LONGJMP calls already have an edge to exit.
      CONST and PURE calls do not need one.
      We don't currently check for CONST and PURE here, although
@@ -7960,6 +7965,13 @@ need_fake_edge_p (gimple *t)
       edge e;
       basic_block bb;
 
+      if (call_flags & (ECF_PURE | ECF_CONST)
+         && !(call_flags & ECF_LOOPING_CONST_OR_PURE))
+       return false;
+
+      /* Function call may do longjmp, terminate program or do other things.
+        Special case noreturn that have non-abnormal edges out as in this case
+        the fact is sufficiently represented by lack of edges out of T.  */
       if (!(call_flags & ECF_NORETURN))
        return true;
 
@@ -8024,7 +8036,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
       if (!gsi_end_p (gsi))
        t = gsi_stmt (gsi);
 
-      if (t && need_fake_edge_p (t))
+      if (t && stmt_can_terminate_bb_p (t))
        {
          edge e;
 
@@ -8059,7 +8071,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
          do
            {
              stmt = gsi_stmt (gsi);
-             if (need_fake_edge_p (stmt))
+             if (stmt_can_terminate_bb_p (stmt))
                {
                  edge e;
 
index 732e06a3553d7fa0ecb66f18945b895b23590846..182753cef3da63fc12158ffef0a8704784a6fdd6 100644 (file)
@@ -2159,7 +2159,6 @@ loop_only_exit_p (const struct loop *loop, const_edge exit)
   basic_block *body;
   gimple_stmt_iterator bsi;
   unsigned i;
-  gimple *call;
 
   if (exit != single_exit (loop))
     return false;
@@ -2168,17 +2167,8 @@ loop_only_exit_p (const struct loop *loop, const_edge exit)
   for (i = 0; i < loop->num_nodes; i++)
     {
       for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi))
-       {
-         call = gsi_stmt (bsi);
-         if (gimple_code (call) != GIMPLE_CALL)
-           continue;
-
-         if (gimple_has_side_effects (call))
-           {
-             free (body);
-             return false;
-           }
-       }
+       if (stmt_can_terminate_bb_p (gsi_stmt (bsi)))
+         return true;
     }
 
   free (body);