Moving pass_lower_switch after the late jump threading changed the
control flow seen by the uninitialized warning pass, exposing two
false positives (PR107919 and PR44547). Both stem from the same
defect in uninit_analysis::is_use_guarded.
is_use_guarded treats an empty use predicate (the PHI is defined and
used in the same block) as an unguarded use because init_use_preds
returns false when the predicate is empty. That is wrong: whether
such a use is guarded depends solely on the definition predicate, so
fall through and compute it.
An empty (TRUE) use predicate is then matched by m_phi_def_preds being
TRUE, i.e. the value is defined on every path. Several spots made this
mismatch on a TRUE use predicate:
- predicate::simplify_2 folded a tautological disjunction to TRUE by
clearing m_preds but forgot to set m_cval, so a definition
predicate that simplified to TRUE was misread as FALSE ("never
defined"). Set m_cval as well.
- the fallback path only recognized an implied guard when the
relaxed definition predicate was a superset of the use predicate,
which is vacuous for a TRUE use predicate; simplify and normalize
the relaxed predicate and, if it is TRUE (defined on every path),
treat it as guarding any use, otherwise fall back to superset_of
for a conditional use.
- normalize() represents an "x & mask" conjunct as a BIT_AND_EXPR
pred_info, but simplify_1b() and pred_neg_p() only handle
comparisons and pass the code to invert_tree_comparison() and
maybe_fold_and_comparisons(), which both trap on anything else.
Skip non-comparison conjuncts in simplify_1b() and let pred_neg_p()
answer "not a negation" for them rather than comparing their bare
codes. This makes simplifying an already normalized predicate
safe, as the fallback above now does.
- drop_conjuncts_implied_by() can remove every conjunct of a chain;
the resulting TRUE chain is neither reported as TRUE nor removed,
leaving an empty chain in the predicate. Like simplify_2(), turn
that into an empty predicate with m_cval set.
gcc/
* gimple-predicate-analysis.cc (pred_neg_p): Return false for
non-comparison operands instead of inverting their code.
(predicate::drop_conjuncts_implied_by): Simplify the whole
predicate to TRUE when it empties a chain.
(simplify_1b): Skip non-comparison pred pairs.
(predicate::simplify_2): Set m_cval when a disjunction simplifies
to true.
(uninit_analysis::is_use_guarded): Do not return early for an
empty use predicate; skip the overlap pruning and the superset
test for an unconditional use, which superset_of() cannot prove;
simplify and normalize the relaxed definition predicate in the
fallback and treat a TRUE relaxed predicate as guarding any use.
---
gcc/gimple-predicate-analysis.cc | 78 +++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 16 deletions(-)
diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc
index 384fe32078e..0b6c3f64efc 100644
--- a/gcc/gimple-predicate-analysis.cc
+++ b/gcc/gimple-predicate-analysis.cc
@@ -62,11 +62,17 @@ pred_neg_p (const pred_info &x1, const pred_info &x2)
|| !operand_equal_p (x1.pred_rhs, x2.pred_rhs, 0))
return false;
- tree_code c1 = x1.cond_code, c2;
+ tree_code c1 = x1.cond_code, c2 = x2.cond_code;
if (x1.invert == x2.invert)
- c2 = invert_tree_comparison (x2.cond_code, false);
- else
- c2 = x2.cond_code;
+ {
+ /* Only comparisons have a complement; an "x & mask" conjunct is a
+ BIT_AND_EXPR pred_info (see normalize()) and is never the negation
+ of anything, while invert_tree_comparison() would trap on it. */
+ if (TREE_CODE_CLASS (c1) != tcc_comparison
+ || TREE_CODE_CLASS (c2) != tcc_comparison)
+ return false;
+ c2 = invert_tree_comparison (c2, false);
+ }
return c1 == c2;
}
@@ -828,7 +834,9 @@ predicate::superset_of (const predicate &preds) const
/* Remove from every chain in *THIS any (comparison) conjunct whose domain is
a superset of every predicate in EDGE_CONDS, i.e. a conjunct implied by all
- of them. Returns true if any conjunct was removed. */
+ of them. Returns true if any conjunct was removed. If all the conjuncts
+ of a chain are removed the chain is TRUE, and with it the whole predicate,
+ which is then left empty with M_CVAL set. */
bool
predicate::drop_conjuncts_implied_by (const vec<pred_info> &edge_conds)
@@ -858,6 +866,18 @@ predicate::drop_conjuncts_implied_by (const vec<pred_info>
&edge_conds)
else
j++;
}
+
+ /* An empty conjunct is TRUE, and so is the OR of the chains. Making
+ that explicit keeps is_true() in sync with superset_of() and spares
+ the callers from having to deal with empty chains. */
+ if (chain.is_empty ())
+ {
+ for (unsigned k = 0; k < m_preds.length (); k++)
+ m_preds[k].release ();
+ m_preds.truncate (0);
+ m_cval = true;
+ return true;
+ }
}
return changed;
}
@@ -1310,6 +1330,14 @@ simplify_1b (pred_chain &chain)
&& CONSTANT_CLASS_P (b_pred.pred_rhs))))
continue;
+ /* Only comparison conjuncts can be combined. An "x & mask"
+ conjunct is a BIT_AND_EXPR pred_info (see normalize()), and
+ inverting it or feeding it to maybe_fold_and_comparisons()
+ would run into invert_tree_comparison()'s gcc_unreachable(). */
+ if (TREE_CODE_CLASS (a_pred.cond_code) != tcc_comparison
+ || TREE_CODE_CLASS (b_pred.cond_code) != tcc_comparison)
+ continue;
+
tree_code a_code = a_pred.cond_code;
if (a_pred.invert)
a_code = invert_tree_comparison (a_code, false);
@@ -1403,6 +1431,8 @@ predicate::simplify_2 ()
for (unsigned k = 0; k < m_preds.length (); ++k)
m_preds[k].release ();
m_preds.truncate (0);
+ /* The whole disjunction has simplified to true. */
+ m_cval = true;
}
break;
}
@@ -2258,18 +2288,22 @@ uninit_analysis::is_use_guarded (gimple *use_stmt,
basic_block use_bb,
into its use. This will be empty if the PHI is defined and used
in the same bb. */
predicate use_preds (true);
- if (!init_use_preds (use_preds, def_bb, use_bb))
- return false;
+ init_use_preds (use_preds, def_bb, use_bb);
+ /* init_use_preds() returns false for an empty (unconditional) use
+ predicate. That does not make the use unguarded: whether it is
+ guarded then depends solely on the definition predicate, which is
+ computed below. */
use_preds.simplify (use_stmt, /*is_use=*/true);
use_preds.normalize (use_stmt, /*is_use=*/true);
if (use_preds.is_false ())
return true;
- if (use_preds.is_true ())
- return false;
- /* Try to prune the dead incoming phi edges. */
- if (!overlap (phi, opnds, visited, use_preds))
+ /* Try to prune the dead incoming phi edges. This requires a non-trivial
+ use predicate; an unconditional use (USE_PREDS is TRUE) has nothing to
+ check against. */
+ if (!use_preds.is_true ()
+ && !overlap (phi, opnds, visited, use_preds))
{
if (DEBUG_PREDICATE_ANALYZER && dump_file)
fputs ("found predicate overlap\n", dump_file);
@@ -2293,8 +2327,11 @@ uninit_analysis::is_use_guarded (gimple *use_stmt,
basic_block use_bb,
/* Return true if the predicate guarding the valid definition (i.e.,
*THIS) is a superset of the predicate guarding the use (i.e.,
- USE_PREDS). */
- if (m_phi_def_preds.superset_of (use_preds))
+ USE_PREDS). An unconditional use (USE_PREDS is TRUE) is guarded only
+ if the value is defined on every path; that case was handled above (an
+ empty definition predicate returns early), and superset_of() is vacuous
+ for a TRUE use predicate, so there is nothing left to test here. */
+ if (!use_preds.is_true () && m_phi_def_preds.superset_of (use_preds))
return true;
/* The superset test fails when a guard that distinguishes the defined from
@@ -2330,9 +2367,18 @@ uninit_analysis::is_use_guarded (gimple *use_stmt,
basic_block use_bb,
if (!edge_conds.is_empty ())
{
predicate relaxed (m_phi_def_preds);
- if (relaxed.drop_conjuncts_implied_by (edge_conds)
- && relaxed.superset_of (use_preds))
- return true;
+ if (relaxed.drop_conjuncts_implied_by (edge_conds))
+ {
+ relaxed.simplify (phi);
+ relaxed.normalize (phi);
+ /* A definition predicate that simplifies to TRUE guards any use;
+ conversely an unconditional use (USE_PREDS is TRUE) is guarded
+ only by a TRUE definition predicate, for which superset_of()
+ is vacuous. */
+ if (relaxed.is_true ()
+ || (!use_preds.is_true () && relaxed.superset_of (use_preds)))
+ return true;
+ }
}
return false;
--
2.34.1