diff options
author | David Malcolm <dmalcolm@redhat.com> | 2021-07-15 15:01:57 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2021-07-15 15:01:57 -0400 |
commit | a9241df96e1950c630550ada9371c0b4a03496cf (patch) | |
tree | 8223a597e534cc582599264829b4c0bb2e7f7ac6 | |
parent | 797358f42fab5ee58a893b68ed18f6ea05eff634 (diff) | |
download | gcc-a9241df96e1950c630550ada9371c0b4a03496cf.zip gcc-a9241df96e1950c630550ada9371c0b4a03496cf.tar.gz gcc-a9241df96e1950c630550ada9371c0b4a03496cf.tar.bz2 |
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>
-rw-r--r-- | gcc/analyzer/state-purge.cc | 37 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/phi-1.c | 24 |
2 files changed, 58 insertions, 3 deletions
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc index 70a09ed..e82ea87 100644 --- a/gcc/analyzer/state-purge.cc +++ b/gcc/analyzer/state-purge.cc @@ -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; + } } } diff --git a/gcc/testsuite/gcc.dg/analyzer/phi-1.c b/gcc/testsuite/gcc.dg/analyzer/phi-1.c new file mode 100644 index 0000000..0926003 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/phi-1.c @@ -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); +} |