Commit 127bf422 by Martin Jambor

ipa-sra: Do not remove statements necessary because of non-call EH (PR 95113)

PR 95113 revealed that when reasoning about which parameters are dead,
IPA-SRA does not perform the same check related to non-call exceptions
as tree DCE.  It most certainly should and so this patch moves the
condition used in tree-ssa-dce.c into a separate predicate (in
tree-eh.c) and uses it from both places.

gcc/ChangeLog:

2020-05-27  Martin Jambor  <mjambor@suse.cz>

	PR ipa/95113
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Move non-call
	exceptions check to...
	* tree-eh.c (stmt_unremovable_because_of_non_call_eh_p): ...this
	new function.
	* tree-eh.h (stmt_unremovable_because_of_non_call_eh_p): Declare it.
	* ipa-sra.c (isra_track_scalar_value_uses): Use it.  New parameter
	fun.

gcc/testsuite/ChangeLog:

2020-05-27  Martin Jambor  <mjambor@suse.cz>

	PR ipa/95113
	* gcc.dg/ipa/pr95113.c: New test.

(cherry picked from commit 1980ffec48c6fa41396bea66366f2e591798e1e1)
parent e4f719b4
......@@ -795,17 +795,17 @@ get_single_param_flow_source (const isra_param_flow *param_flow)
}
/* Inspect all uses of NAME and simple arithmetic calculations involving NAME
in NODE and return a negative number if any of them is used for something
else than either an actual call argument, simple arithmetic operation or
debug statement. If there are no such uses, return the number of actual
arguments that this parameter eventually feeds to (or zero if there is none).
For any such parameter, mark PARM_NUM as one of its sources. ANALYZED is a
bitmap that tracks which SSA names we have already started
investigating. */
in FUN represented with NODE and return a negative number if any of them is
used for something else than either an actual call argument, simple
arithmetic operation or debug statement. If there are no such uses, return
the number of actual arguments that this parameter eventually feeds to (or
zero if there is none). For any such parameter, mark PARM_NUM as one of its
sources. ANALYZED is a bitmap that tracks which SSA names we have already
started investigating. */
static int
isra_track_scalar_value_uses (cgraph_node *node, tree name, int parm_num,
bitmap analyzed)
isra_track_scalar_value_uses (function *fun, cgraph_node *node, tree name,
int parm_num, bitmap analyzed)
{
int res = 0;
imm_use_iterator imm_iter;
......@@ -859,8 +859,9 @@ isra_track_scalar_value_uses (cgraph_node *node, tree name, int parm_num,
}
res += all_uses;
}
else if ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
|| gimple_code (stmt) == GIMPLE_PHI)
else if (!stmt_unremovable_because_of_non_call_eh_p (fun, stmt)
&& ((is_gimple_assign (stmt) && !gimple_has_volatile_ops (stmt))
|| gimple_code (stmt) == GIMPLE_PHI))
{
tree lhs;
if (gimple_code (stmt) == GIMPLE_PHI)
......@@ -876,7 +877,7 @@ isra_track_scalar_value_uses (cgraph_node *node, tree name, int parm_num,
gcc_assert (!gimple_vdef (stmt));
if (bitmap_set_bit (analyzed, SSA_NAME_VERSION (lhs)))
{
int tmp = isra_track_scalar_value_uses (node, lhs, parm_num,
int tmp = isra_track_scalar_value_uses (fun, node, lhs, parm_num,
analyzed);
if (tmp < 0)
{
......@@ -927,7 +928,8 @@ isra_track_scalar_param_local_uses (function *fun, cgraph_node *node, tree parm,
return true;
bitmap analyzed = BITMAP_ALLOC (NULL);
int call_uses = isra_track_scalar_value_uses (node, name, parm_num, analyzed);
int call_uses = isra_track_scalar_value_uses (fun, node, name, parm_num,
analyzed);
BITMAP_FREE (analyzed);
if (call_uses < 0)
return true;
......
/* { dg-do run } */
/* { dg-options "-O2 -fexceptions -fnon-call-exceptions" } */
/* { dg-require-effective-target exceptions } */
int a, b;
static inline long int
foo (long int x, int y)
{
if (y == 0)
return 0;
if (x == -1 && y == -1)
return 0;
return x / y;
}
static inline int
bar (int *p)
{
int c = foo (a, 1) + *p;
return b;
}
int
main ()
{
int d = 0;
b = foo (1, 1);
bar (&d);
return 0;
}
......@@ -2939,6 +2939,16 @@ stmt_could_throw_p (function *fun, gimple *stmt)
}
}
/* Return true if STMT in function FUN must be assumed necessary because of
non-call exceptions. */
bool
stmt_unremovable_because_of_non_call_eh_p (function *fun, gimple *stmt)
{
return (fun->can_throw_non_call_exceptions
&& !fun->can_delete_dead_exceptions
&& stmt_could_throw_p (fun, stmt));
}
/* Return true if expression T could throw an exception. */
......
......@@ -39,6 +39,7 @@ extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
extern bool tree_could_trap_p (tree);
extern tree rewrite_to_non_trapping_overflow (tree);
extern bool stmt_could_throw_p (function *, gimple *);
extern bool stmt_unremovable_because_of_non_call_eh_p (function *, gimple *);
extern bool tree_could_throw_p (tree);
extern bool stmt_can_throw_external (function *, gimple *);
extern bool stmt_can_throw_internal (function *, gimple *);
......
......@@ -201,9 +201,7 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
{
/* With non-call exceptions, we have to assume that all statements could
throw. If a statement could throw, it can be deemed necessary. */
if (cfun->can_throw_non_call_exceptions
&& !cfun->can_delete_dead_exceptions
&& stmt_could_throw_p (cfun, stmt))
if (stmt_unremovable_because_of_non_call_eh_p (cfun, stmt))
{
mark_stmt_necessary (stmt, true);
return;
......
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