Remove uninit_analysis::use_cannot_happen
As written earlier uninit_analysis::use_cannot_happen is duplicate functionality implemented in a complement way, not adhering to the idea of disproving a may-uninit use and eventually (I have not yet found a testcase it helps to avoid false positives) avoiding false positives because of this or different ways it imposes limits on the predicate computations. This patch removes it. * gimple-predicate-analysis.h (uninit_analysis::use_cannot_happen): Remove. * gimple-predicate-analysis.cc (can_be_invalidated_p): Remove. (uninit_analysis::use_cannot_happen): Likewise. (uninit_analysis::is_use_guarded): Do not call use_cannot_happen. (dump_predicates): Remove. (simple_control_dep_chain): Remove edge overload.
This commit is contained in:
parent
fc1b5707fa
commit
8e08906973
2 changed files with 0 additions and 213 deletions
|
@ -209,32 +209,6 @@ dump_pred_chain (const pred_chain &chain)
|
|||
}
|
||||
}
|
||||
|
||||
/* Dump the predicate chain PREDS for STMT, prefixed by MSG. */
|
||||
|
||||
static void
|
||||
dump_predicates (gimple *stmt, const pred_chain_union &preds, const char *msg)
|
||||
{
|
||||
fprintf (dump_file, "%s", msg);
|
||||
if (stmt)
|
||||
{
|
||||
print_gimple_stmt (dump_file, stmt, 0);
|
||||
fprintf (dump_file, "is guarded by:\n");
|
||||
}
|
||||
|
||||
unsigned np = preds.length ();
|
||||
if (np > 1)
|
||||
fprintf (dump_file, "OR (");
|
||||
for (unsigned i = 0; i < np; i++)
|
||||
{
|
||||
dump_pred_chain (preds[i]);
|
||||
if (i < np - 1)
|
||||
fprintf (dump_file, ", ");
|
||||
else if (i > 0)
|
||||
fputc (')', dump_file);
|
||||
}
|
||||
fputc ('\n', dump_file);
|
||||
}
|
||||
|
||||
/* Dump the first NCHAINS elements of the DEP_CHAINS array into DUMP_FILE. */
|
||||
|
||||
static void
|
||||
|
@ -1071,13 +1045,6 @@ simple_control_dep_chain (vec<edge>& chain, basic_block from, basic_block to)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
simple_control_dep_chain (vec<edge>& chain, basic_block from, edge to)
|
||||
{
|
||||
chain.safe_push (to);
|
||||
simple_control_dep_chain (chain, from, to->src);
|
||||
}
|
||||
|
||||
/* Perform a DFS walk on predecessor edges to mark the region denoted
|
||||
by the EXIT edge and DOM which dominates EXIT->src, including DOM.
|
||||
Blocks in the region are marked with FLAG and added to BBS. BBS is
|
||||
|
@ -1242,180 +1209,6 @@ compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb,
|
|||
return found_cd_chain;
|
||||
}
|
||||
|
||||
/* Return true if PRED can be invalidated by any predicate in GUARD. */
|
||||
|
||||
static bool
|
||||
can_be_invalidated_p (const pred_info &pred, const pred_chain &guard)
|
||||
{
|
||||
if (dump_file && dump_flags & TDF_DETAILS)
|
||||
{
|
||||
fprintf (dump_file, "Testing if predicate: ");
|
||||
dump_pred_info (pred);
|
||||
fprintf (dump_file, "\n...can be invalidated by a USE guard of: ");
|
||||
dump_pred_chain (guard);
|
||||
fputc ('\n', dump_file);
|
||||
}
|
||||
|
||||
unsigned n = guard.length ();
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
if (pred_neg_p (pred, guard[i]))
|
||||
{
|
||||
if (dump_file && dump_flags & TDF_DETAILS)
|
||||
{
|
||||
fprintf (dump_file, " Predicate invalidated by: ");
|
||||
dump_pred_info (guard[i]);
|
||||
fputc ('\n', dump_file);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return true if all predicates in PREDS are invalidated by GUARD being
|
||||
true. */
|
||||
|
||||
static bool
|
||||
can_be_invalidated_p (const pred_chain_union &preds, const pred_chain &guard)
|
||||
{
|
||||
if (preds.is_empty ())
|
||||
return false;
|
||||
|
||||
if (dump_file && dump_flags & TDF_DETAILS)
|
||||
dump_predicates (NULL, preds,
|
||||
"Testing if anything here can be invalidated: ");
|
||||
|
||||
for (unsigned i = 0; i < preds.length (); ++i)
|
||||
{
|
||||
const pred_chain &chain = preds[i];
|
||||
unsigned j;
|
||||
for (j = 0; j < chain.length (); ++j)
|
||||
if (can_be_invalidated_p (chain[j], guard))
|
||||
break;
|
||||
|
||||
/* If we were unable to invalidate any predicate in C, then there
|
||||
is a viable path from entry to the PHI where the PHI takes
|
||||
an interesting value and continues to a use of the PHI. */
|
||||
if (j == chain.length ())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true if none of the PHI arguments in OPNDS is used given
|
||||
the use guards in *THIS that guard the PHI's use. */
|
||||
|
||||
bool
|
||||
uninit_analysis::use_cannot_happen (gphi *phi, unsigned opnds, const predicate &use_preds)
|
||||
{
|
||||
if (!m_eval.phi_arg_set (phi))
|
||||
return false;
|
||||
|
||||
/* PHI_USE_GUARDS are OR'ed together. If we have more than one
|
||||
possible guard, there's no way of knowing which guard was true.
|
||||
In that case compute the intersection of all use predicates
|
||||
and use that. */
|
||||
const predicate &phi_use_guards = use_preds;
|
||||
const pred_chain *use_guard = &phi_use_guards.chain() [0];
|
||||
pred_chain phi_use_guard_intersection = vNULL;
|
||||
if (phi_use_guards.chain ().length () != 1)
|
||||
{
|
||||
phi_use_guard_intersection = use_guard->copy ();
|
||||
for (unsigned i = 1; i < phi_use_guards.chain ().length (); ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < phi_use_guard_intersection.length ();)
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k < phi_use_guards.chain ()[i].length (); ++k)
|
||||
if (pred_equal_p (phi_use_guards.chain ()[i][k],
|
||||
phi_use_guard_intersection[j]))
|
||||
break;
|
||||
if (k == phi_use_guards.chain ()[i].length ())
|
||||
phi_use_guard_intersection.unordered_remove (j);
|
||||
else
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (phi_use_guard_intersection.is_empty ())
|
||||
{
|
||||
phi_use_guard_intersection.release ();
|
||||
return false;
|
||||
}
|
||||
use_guard = &phi_use_guard_intersection;
|
||||
}
|
||||
|
||||
basic_block phi_bb = gimple_bb (phi);
|
||||
/* Find the closest dominating bb to be the control dependence root. */
|
||||
basic_block cd_root = get_immediate_dominator (CDI_DOMINATORS, phi_bb);
|
||||
if (!cd_root)
|
||||
return false;
|
||||
|
||||
/* Look for the control dependencies of all the interesting operands
|
||||
and build guard predicates describing them. */
|
||||
unsigned n = gimple_phi_num_args (phi);
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
if (!MASK_TEST_BIT (opnds, i))
|
||||
continue;
|
||||
|
||||
edge e = gimple_phi_arg_edge (phi, i);
|
||||
auto_vec<edge> dep_chains[MAX_NUM_CHAINS];
|
||||
auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain;
|
||||
unsigned num_chains = 0;
|
||||
unsigned num_calls = 0;
|
||||
|
||||
/* Build the control dependency chain for the PHI argument... */
|
||||
if (!compute_control_dep_chain (cd_root,
|
||||
e->src, dep_chains, &num_chains,
|
||||
cur_chain, &num_calls))
|
||||
{
|
||||
gcc_assert (num_chains == 0);
|
||||
/* If compute_control_dep_chain bailed out due to limits
|
||||
build a partial sparse path using dominators. Collect
|
||||
only edges whose predicates are always true when reaching E. */
|
||||
simple_control_dep_chain (dep_chains[0], cd_root, e);
|
||||
num_chains++;
|
||||
}
|
||||
/* Update the chains with the phi operand edge. */
|
||||
else if (EDGE_COUNT (e->src->succs) > 1)
|
||||
{
|
||||
for (unsigned j = 0; j < num_chains; j++)
|
||||
dep_chains[j].safe_push (e);
|
||||
}
|
||||
|
||||
if (DEBUG_PREDICATE_ANALYZER && dump_file)
|
||||
{
|
||||
fprintf (dump_file, "predicate::use_cannot_happen (...) "
|
||||
"dep_chains for arg %u:\n\t", i);
|
||||
dump_dep_chains (dep_chains, num_chains);
|
||||
}
|
||||
|
||||
/* ...and convert it into a set of predicates guarding its
|
||||
definition. */
|
||||
predicate def_preds;
|
||||
def_preds.init_from_control_deps (dep_chains, num_chains);
|
||||
if (def_preds.is_empty ())
|
||||
/* If there's no predicate there's no basis to rule the use out. */
|
||||
return false;
|
||||
|
||||
def_preds.simplify ();
|
||||
def_preds.normalize ();
|
||||
|
||||
/* Can the guard for this PHI argument be negated by the one
|
||||
guarding the PHI use? */
|
||||
if (!can_be_invalidated_p (def_preds.chain (), *use_guard))
|
||||
{
|
||||
phi_use_guard_intersection.release ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
phi_use_guard_intersection.release ();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implemented simplifications:
|
||||
|
||||
1) ((x IOR y) != 0) AND (x != 0) is equivalent to (x != 0);
|
||||
|
@ -2391,11 +2184,6 @@ uninit_analysis::is_use_guarded (gimple *use_stmt, basic_block use_bb,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* We might be able to prove that if the control dependencies for OPNDS
|
||||
are true, the control dependencies for USE_STMT can never be true. */
|
||||
if (use_cannot_happen (phi, opnds, use_preds))
|
||||
return true;
|
||||
|
||||
if (m_phi_def_preds.is_empty ())
|
||||
{
|
||||
/* Lazily initialize *THIS from PHI. */
|
||||
|
|
|
@ -137,7 +137,6 @@ private:
|
|||
bool prune_phi_opnds (gphi *, unsigned, gphi *, tree, tree_code,
|
||||
hash_set<gphi *> *, bitmap *);
|
||||
bool overlap (gphi *, unsigned, hash_set<gphi *> *, const predicate &);
|
||||
bool use_cannot_happen (gphi *, unsigned, const predicate &);
|
||||
|
||||
void collect_phi_def_edges (gphi *, basic_block, vec<edge> *,
|
||||
hash_set<gimple *> *);
|
||||
|
|
Loading…
Add table
Reference in a new issue