diff options
author | Richard Biener <rguenther@suse.de> | 2022-08-29 12:20:10 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2022-08-30 09:27:07 +0200 |
commit | 4a8f98fa3bef754abedc3ed7a1839b4c8c782730 (patch) | |
tree | 9f3f57754d2a717ce622be83e77d63d6ace08dfb /gcc/gimple-predicate-analysis.cc | |
parent | 37ebaabde2b88d446369240ae8f03b8e6a284a7b (diff) | |
download | gcc-4a8f98fa3bef754abedc3ed7a1839b4c8c782730.zip gcc-4a8f98fa3bef754abedc3ed7a1839b4c8c782730.tar.gz gcc-4a8f98fa3bef754abedc3ed7a1839b4c8c782730.tar.bz2 |
Make uninit PHI processing more consistent
Currently the main working of the maybe-uninit pass is to scan over
all PHIs with possibly undefined arguments, diagnosing whether there's
a direct not guarded use. For not guarded uses in PHIs those are queued for
later processing and to make the uninit analysis PHI def handling work,
mark the PHI def as possibly uninitialized. But this happens only
for those PHI uses that happen to be seen before a direct not guarded
use and whether all arguments of a PHI node which are defined by a PHI
are properly marked as maybe uninitialized depends on the processing
order.
The following changes the uninit pass to perform an RPO walk over
the function, ensuring that PHI argument defs are visited before
the PHI node (besides backedge uses which we ignore already),
getting rid of the worklist. It also makes sure to process all
PHI uses, but recording those that are properly guarded so they
are not treated as maybe undefined when processing the PHI use
later.
Overall this should make behavior more consistent, avoid some
false negative because of the previous early out and order issue,
and avoid some false positive because of the missed recording
of guarded PHI uses.
The patch correctly diagnoses an uninitalized use of 'regnum'
in store_bit_field_1 and also diagnoses an uninitialized use of
best_match::m_best_candidate_len in c-decl.cc which I've chosen to
silence by initializing m_best_candidate_len. The warning is
a false positive but GCC cannot see that m_best_candidate_len is
initialized when m_best_candidate is not NULL so from this
perspective this was a false negative. I've added
g++.dg/uninit-pred-5.C with a reduced testcase that nicely shows
how the previous behavior missed the diagnostic because the
worklist ended up visiting the PHI with the dependend uninit
value before visiting the PHIs producing it.
* gimple-predicate-analysis.h (uninit_analysis::operator()):
Remove.
* gimple-predicate-analysis.cc
(uninit_analysis::collect_phi_def_edges): Use phi_arg_set,
simplify a bit.
* tree-ssa-uninit.cc (defined_args): New global.
(compute_uninit_opnds_pos): Mask with the recorded set
of guarded maybe-uninitialized uses.
(uninit_undef_val_t::operator()): Remove.
(find_uninit_use): Process all PHI uses, recording the
guarded ones and marking the PHI result as uninitialized
consistently.
(warn_uninitialized_phi): Adjust.
(execute_late_warn_uninitialized): Get rid of the PHI worklist
and instead walk the function in RPO order.
* spellcheck.h (best_match::m_best_candidate_len): Initialize.
* g++.dg/uninit-pred-5.C: New testcase.
Diffstat (limited to 'gcc/gimple-predicate-analysis.cc')
-rw-r--r-- | gcc/gimple-predicate-analysis.cc | 49 |
1 files changed, 20 insertions, 29 deletions
diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index e388bb3..3f9b80d 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -543,35 +543,13 @@ uninit_analysis::collect_phi_def_edges (gphi *phi, basic_block cd_root, return; unsigned n = gimple_phi_num_args (phi); + unsigned opnds_arg_phi = m_eval.phi_arg_set (phi); for (unsigned i = 0; i < n; i++) { - edge opnd_edge = gimple_phi_arg_edge (phi, i); - tree opnd = gimple_phi_arg_def (phi, i); - - if (TREE_CODE (opnd) == SSA_NAME) - { - gimple *def = SSA_NAME_DEF_STMT (opnd); - - if (!m_eval (opnd)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, - "\tFound def edge %i -> %i for cd_root %i " - "and operand %u of: ", - opnd_edge->src->index, opnd_edge->dest->index, - cd_root->index, i); - print_gimple_stmt (dump_file, phi, 0); - } - edges->safe_push (opnd_edge); - } - else if (gimple_code (def) == GIMPLE_PHI - && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root)) - collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges, - visited); - } - else + if (!MASK_TEST_BIT (opnds_arg_phi, i)) { + /* Add the edge for a not maybe-undefined edge value. */ + edge opnd_edge = gimple_phi_arg_edge (phi, i); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, @@ -581,9 +559,22 @@ uninit_analysis::collect_phi_def_edges (gphi *phi, basic_block cd_root, cd_root->index, i); print_gimple_stmt (dump_file, phi, 0); } - - if (!m_eval (opnd)) - edges->safe_push (opnd_edge); + edges->safe_push (opnd_edge); + continue; + } + else + { + tree opnd = gimple_phi_arg_def (phi, i); + if (TREE_CODE (opnd) == SSA_NAME) + { + gimple *def = SSA_NAME_DEF_STMT (opnd); + if (gimple_code (def) == GIMPLE_PHI + && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root)) + /* Process PHI defs of maybe-undefined edge values + recursively. */ + collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges, + visited); + } } } } |