From: David Malcolm Date: Thu, 15 Jul 2021 19:01:57 +0000 (-0400) Subject: analyzer: handle self-referential phis X-Git-Tag: upstream/12.2.0~6363 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a9241df96e1950c630550ada9371c0b4a03496cf;p=platform%2Fupstream%2Fgcc.git 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 --- 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 + 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 + 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); +}