analyzer: handle self-referential phis
gcc/analyzer/ChangeLog: * state-purge.cc (self_referential_phi_p): New. (state_purge_per_ssa_name::process_point): Don't purge an SSA name at its def-stmt if the def-stmt is self-referential. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/phi-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
797358f42f
commit
a9241df96e
2 changed files with 58 additions and 3 deletions
|
@ -288,6 +288,20 @@ state_purge_per_ssa_name::add_to_worklist (const function_point &point,
|
|||
}
|
||||
}
|
||||
|
||||
/* Does this phi depend on itself?
|
||||
e.g. in:
|
||||
added_2 = PHI <added_6(2), added_2(3), added_11(4)>
|
||||
the middle defn (from edge 3) requires added_2 itself. */
|
||||
|
||||
static bool
|
||||
self_referential_phi_p (const gphi *phi)
|
||||
{
|
||||
for (unsigned i = 0; i < gimple_phi_num_args (phi); i++)
|
||||
if (gimple_phi_arg_def (phi, i) == gimple_phi_result (phi))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Process POINT, popped from WORKLIST.
|
||||
Iterate over predecessors of POINT, adding to WORKLIST. */
|
||||
|
||||
|
@ -326,11 +340,28 @@ state_purge_per_ssa_name::process_point (const function_point &point,
|
|||
!gsi_end_p (gpi); gsi_next (&gpi))
|
||||
{
|
||||
gphi *phi = gpi.phi ();
|
||||
/* Are we at the def-stmt for m_name? */
|
||||
if (phi == def_stmt)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("def stmt within phis; terminating");
|
||||
return;
|
||||
/* Does this phi depend on itself?
|
||||
e.g. in:
|
||||
added_2 = PHI <added_6(2), added_2(3), added_11(4)>
|
||||
the middle defn (from edge 3) requires added_2 itself
|
||||
so we can't purge it here. */
|
||||
if (self_referential_phi_p (phi))
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("self-referential def stmt within phis;"
|
||||
" continuing");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we can stop here, so that m_name
|
||||
can be purged. */
|
||||
if (logger)
|
||||
logger->log ("def stmt within phis; terminating");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
24
gcc/testsuite/gcc.dg/analyzer/phi-1.c
Normal file
24
gcc/testsuite/gcc.dg/analyzer/phi-1.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* { dg-do "compile" } */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
#define NULL ((void *) 0)
|
||||
|
||||
extern const char *foo (void);
|
||||
extern size_t bar (void);
|
||||
|
||||
void
|
||||
_nl_expand_alias (const char *locale_alias_path)
|
||||
{
|
||||
size_t added;
|
||||
do
|
||||
{
|
||||
added = 0;
|
||||
while (added == 0 && locale_alias_path[0] != '\0')
|
||||
{
|
||||
const char *start = foo ();
|
||||
if (start < locale_alias_path)
|
||||
added = bar ();
|
||||
}
|
||||
}
|
||||
while (added != 0);
|
||||
}
|
Loading…
Add table
Reference in a new issue