aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-predicate-analysis.cc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-11-30 10:58:13 +0100
committerRichard Biener <rguenther@suse.de>2023-11-30 13:31:25 +0100
commit8a6062a47b33da6d961c6354fd5788bc46aef0a9 (patch)
tree72cb3f46ddf93a333e947d45d0d03b8eed68a41c /gcc/gimple-predicate-analysis.cc
parent303195e2a6b6f0e8f42e0578b61f9f37c6250beb (diff)
downloadgcc-8a6062a47b33da6d961c6354fd5788bc46aef0a9.zip
gcc-8a6062a47b33da6d961c6354fd5788bc46aef0a9.tar.gz
gcc-8a6062a47b33da6d961c6354fd5788bc46aef0a9.tar.bz2
tree-optimization/112766 - improve pruning of uninit diagnostics
Uninit diagnostics has code to prune based on incoming PHI args that prove the uninit code is never executed. But that only looks at the first found flag candidate while in the PRs case only the second candidate would be the one to prune on. The following patch makes us consider all of the flag candidates which is cycles well spent IMHO. PR tree-optimization/112766 * gimple-predicate-analysis.cc (find_var_cmp_const): Support continuing the iteration and report every candidate. (uninit_analysis::overlap): Iterate over all flag var candidates. * g++.dg/torture/uninit-pr112766.C: New testcase.
Diffstat (limited to 'gcc/gimple-predicate-analysis.cc')
-rw-r--r--gcc/gimple-predicate-analysis.cc78
1 files changed, 30 insertions, 48 deletions
diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
index ad2c355..5e231a6 100644
--- a/gcc/gimple-predicate-analysis.cc
+++ b/gcc/gimple-predicate-analysis.cc
@@ -244,21 +244,18 @@ find_matching_predicate_in_rest_chains (const pred_info &pred,
of that's the form "FLAG_VAR CMP FLAG_VAR" with value range info.
PHI is the phi node whose incoming (interesting) paths need to be
examined. On success, return the comparison code, set defintion
- gimple of FLAG_DEF and BOUNDARY_CST. Otherwise return ERROR_MARK. */
+ gimple of FLAG_DEF and BOUNDARY_CST. Otherwise return ERROR_MARK.
+ I is the running iterator so the function can be called repeatedly
+ to gather all candidates. */
static tree_code
find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
- tree *boundary_cst)
+ tree *boundary_cst, unsigned &i)
{
- tree_code vrinfo_code = ERROR_MARK;
- gimple *vrinfo_def = NULL;
- tree vrinfo_cst = NULL;
-
gcc_assert (preds.length () > 0);
pred_chain chain = preds[0];
- for (unsigned i = 0; i < chain.length (); i++)
+ for (; i < chain.length (); i++)
{
- bool use_vrinfo_p = false;
const pred_info &pred = chain[i];
tree cond_lhs = pred.pred_lhs;
tree cond_rhs = pred.pred_rhs;
@@ -282,8 +279,7 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
}
/* Check if we can take advantage of FLAG_VAR COMP FLAG_VAR predicate
with value range info. Note only first of such case is handled. */
- else if (vrinfo_code == ERROR_MARK
- && TREE_CODE (cond_lhs) == SSA_NAME
+ else if (TREE_CODE (cond_lhs) == SSA_NAME
&& TREE_CODE (cond_rhs) == SSA_NAME)
{
gimple* lhs_def = SSA_NAME_DEF_STMT (cond_lhs);
@@ -331,8 +327,6 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
cond_rhs = wide_int_to_tree (type, min);
else
continue;
-
- use_vrinfo_p = true;
}
else
continue;
@@ -345,27 +339,13 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
|| !find_matching_predicate_in_rest_chains (pred, preds))
continue;
- /* Return if any "flag_var comp const" predicate is found. */
- if (!use_vrinfo_p)
- {
- *boundary_cst = cond_rhs;
- return code;
- }
- /* Record if any "flag_var comp flag_var[vinfo]" predicate is found. */
- else if (vrinfo_code == ERROR_MARK)
- {
- vrinfo_code = code;
- vrinfo_def = *flag_def;
- vrinfo_cst = cond_rhs;
- }
- }
- /* Return the "flag_var cmp flag_var[vinfo]" predicate we found. */
- if (vrinfo_code != ERROR_MARK)
- {
- *flag_def = vrinfo_def;
- *boundary_cst = vrinfo_cst;
+ /* Return predicate found. */
+ *boundary_cst = cond_rhs;
+ ++i;
+ return code;
}
- return vrinfo_code;
+
+ return ERROR_MARK;
}
/* Return true if all interesting opnds are pruned, false otherwise.
@@ -641,27 +621,29 @@ uninit_analysis::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited,
{
gimple *flag_def = NULL;
tree boundary_cst = NULL_TREE;
- bitmap visited_flag_phis = NULL;
/* Find within the common prefix of multiple predicate chains
a predicate that is a comparison of a flag variable against
a constant. */
- tree_code cmp_code = find_var_cmp_const (use_preds.chain (), phi, &flag_def,
- &boundary_cst);
- if (cmp_code == ERROR_MARK)
- return true;
-
- /* Now check all the uninit incoming edges have a constant flag
- value that is in conflict with the use guard/predicate. */
- gphi *phi_def = as_a<gphi *> (flag_def);
- bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst,
- cmp_code, visited,
- &visited_flag_phis);
-
- if (visited_flag_phis)
- BITMAP_FREE (visited_flag_phis);
+ unsigned i = 0;
+ tree_code cmp_code;
+ while ((cmp_code = find_var_cmp_const (use_preds.chain (), phi, &flag_def,
+ &boundary_cst, i)) != ERROR_MARK)
+ {
+ /* Now check all the uninit incoming edges have a constant flag
+ value that is in conflict with the use guard/predicate. */
+ bitmap visited_flag_phis = NULL;
+ gphi *phi_def = as_a<gphi *> (flag_def);
+ bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst,
+ cmp_code, visited,
+ &visited_flag_phis);
+ if (visited_flag_phis)
+ BITMAP_FREE (visited_flag_phis);
+ if (all_pruned)
+ return false;
+ }
- return !all_pruned;
+ return true;
}
/* Return true if two predicates PRED1 and X2 are equivalent. Assume