aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-predicate-analysis.cc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2022-08-29 12:20:10 +0200
committerRichard Biener <rguenther@suse.de>2022-08-30 09:27:07 +0200
commit4a8f98fa3bef754abedc3ed7a1839b4c8c782730 (patch)
tree9f3f57754d2a717ce622be83e77d63d6ace08dfb /gcc/gimple-predicate-analysis.cc
parent37ebaabde2b88d446369240ae8f03b8e6a284a7b (diff)
downloadgcc-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.cc49
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);
+ }
}
}
}