Commit 21bcd7be by Jan Hubicka Committed by Jan Hubicka

gimple.h (stmt_can_terminate_bb_p): New function.

	* 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
parent 91f35b7f
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> 2016-07-14 Richard Biener <rguenther@suse.de>
PR tree-optimization/71866 PR tree-optimization/71866
......
...@@ -1526,6 +1526,7 @@ extern void gimple_seq_set_location (gimple_seq, location_t); ...@@ -1526,6 +1526,7 @@ extern void gimple_seq_set_location (gimple_seq, location_t);
extern void gimple_seq_discard (gimple_seq); extern void gimple_seq_discard (gimple_seq);
extern void maybe_remove_unused_call_args (struct function *, gimple *); extern void maybe_remove_unused_call_args (struct function *, gimple *);
extern bool gimple_inexpensive_call_p (gcall *); extern bool gimple_inexpensive_call_p (gcall *);
extern bool stmt_can_terminate_bb_p (gimple *);
/* Formal (expression) temporary table handling: multiple occurrences of /* Formal (expression) temporary table handling: multiple occurrences of
the same scalar expression are evaluated into the same temporary. */ the same scalar expression are evaluated into the same temporary. */
......
...@@ -7919,15 +7919,20 @@ gimple_block_ends_with_condjump_p (const_basic_block bb) ...@@ -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. /* Return true if statement T may terminate execution of BB in ways not
Helper function for gimple_flow_call_edges_add. */ explicitly represtented in the CFG. */
static bool bool
need_fake_edge_p (gimple *t) stmt_can_terminate_bb_p (gimple *t)
{ {
tree fndecl = NULL_TREE; tree fndecl = NULL_TREE;
int call_flags = 0; 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. /* NORETURN and LONGJMP calls already have an edge to exit.
CONST and PURE calls do not need one. CONST and PURE calls do not need one.
We don't currently check for CONST and PURE here, although We don't currently check for CONST and PURE here, although
...@@ -7960,6 +7965,13 @@ need_fake_edge_p (gimple *t) ...@@ -7960,6 +7965,13 @@ need_fake_edge_p (gimple *t)
edge e; edge e;
basic_block bb; 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)) if (!(call_flags & ECF_NORETURN))
return true; return true;
...@@ -8024,7 +8036,7 @@ gimple_flow_call_edges_add (sbitmap blocks) ...@@ -8024,7 +8036,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
if (!gsi_end_p (gsi)) if (!gsi_end_p (gsi))
t = gsi_stmt (gsi); t = gsi_stmt (gsi);
if (t && need_fake_edge_p (t)) if (t && stmt_can_terminate_bb_p (t))
{ {
edge e; edge e;
...@@ -8059,7 +8071,7 @@ gimple_flow_call_edges_add (sbitmap blocks) ...@@ -8059,7 +8071,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
do do
{ {
stmt = gsi_stmt (gsi); stmt = gsi_stmt (gsi);
if (need_fake_edge_p (stmt)) if (stmt_can_terminate_bb_p (stmt))
{ {
edge e; edge e;
......
...@@ -2159,7 +2159,6 @@ loop_only_exit_p (const struct loop *loop, const_edge exit) ...@@ -2159,7 +2159,6 @@ loop_only_exit_p (const struct loop *loop, const_edge exit)
basic_block *body; basic_block *body;
gimple_stmt_iterator bsi; gimple_stmt_iterator bsi;
unsigned i; unsigned i;
gimple *call;
if (exit != single_exit (loop)) if (exit != single_exit (loop))
return false; return false;
...@@ -2168,17 +2167,8 @@ loop_only_exit_p (const struct loop *loop, const_edge exit) ...@@ -2168,17 +2167,8 @@ loop_only_exit_p (const struct loop *loop, const_edge exit)
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
{ {
for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi)) for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi))
{ if (stmt_can_terminate_bb_p (gsi_stmt (bsi)))
call = gsi_stmt (bsi); return true;
if (gimple_code (call) != GIMPLE_CALL)
continue;
if (gimple_has_side_effects (call))
{
free (body);
return false;
}
}
} }
free (body); free (body);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment