tree-optimization/109342 - wrong code with edge equivalences in VN

The following testcase shows a problem in how we query valitity for
equivalences on edges when the edge is a backedge and thus refering
to a block thats later in the iteration order we use for VN.  That
causes the dominated_by_p_w_unex helper to look at edge executable
state that's not yet computed and thus still at optimistic not
executable state.

The following makes sure to use a plain dominance check in these cases.

	PR tree-optimization/109342
	* tree-ssa-sccvn.cc (vn_nary_op_get_predicated_value): New
	overload for edge.  When that edge is a backedge use
	dominated_by_p directly.

	* g++.dg/torture/pr109342.C: New testcase.
This commit is contained in:
Richard Biener 2023-03-30 11:32:19 +02:00
parent ee6ae8cb47
commit 1d0ba4467d
2 changed files with 60 additions and 10 deletions

View File

@ -0,0 +1,33 @@
// { dg-do run }
unsigned long int var_4 = 42;
unsigned long int var_14 = 10;
unsigned char var_16 = 1;
unsigned short var_18 = 0;
short var_75;
inline const int &foo(const int &b, const int &c)
{
return b < c ? c : b;
}
inline unsigned long &bar(unsigned long &b, unsigned long &c)
{
return !c ? c : b;
}
void __attribute__((noipa))
test(unsigned long var_4, unsigned long var_14,
unsigned char var_16, unsigned short var_18)
{
for (bool h = 0; h < (bool)foo(var_16 ? -7 : 4, var_4 ? var_4 : var_18);
h = 2)
var_75 = bar(var_4, var_14);
}
int main()
{
test(var_4, var_14, var_16, var_18);
if (var_75 != 42)
__builtin_abort();
return 0;
}

View File

@ -4583,22 +4583,39 @@ static bool
dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool);
static tree
vn_nary_op_get_predicated_value (vn_nary_op_t vno, basic_block bb)
vn_nary_op_get_predicated_value (vn_nary_op_t vno, basic_block bb,
edge e = NULL)
{
if (! vno->predicated_values)
return vno->u.result;
for (vn_pval *val = vno->u.values; val; val = val->next)
for (unsigned i = 0; i < val->n; ++i)
/* Do not handle backedge executability optimistically since
when figuring out whether to iterate we do not consider
changed predication. */
if (dominated_by_p_w_unex
(bb, BASIC_BLOCK_FOR_FN (cfun, val->valid_dominated_by_p[i]),
false))
return val->result;
{
basic_block cand
= BASIC_BLOCK_FOR_FN (cfun, val->valid_dominated_by_p[i]);
/* Do not handle backedge executability optimistically since
when figuring out whether to iterate we do not consider
changed predication.
When asking for predicated values on an edge avoid looking
at edge executability for edges forward in our iteration
as well. */
if (e && (e->flags & EDGE_DFS_BACK))
{
if (dominated_by_p (CDI_DOMINATORS, bb, cand))
return val->result;
}
else if (dominated_by_p_w_unex (bb, cand, false))
return val->result;
}
return NULL_TREE;
}
static tree
vn_nary_op_get_predicated_value (vn_nary_op_t vno, edge e)
{
return vn_nary_op_get_predicated_value (vno, e->src, e);
}
/* Insert the rhs of STMT into the current hash table with a value number of
RESULT. */
@ -5928,7 +5945,7 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p)
ops, &vnresult);
if (! val && vnresult && vnresult->predicated_values)
{
val = vn_nary_op_get_predicated_value (vnresult, e->src);
val = vn_nary_op_get_predicated_value (vnresult, e);
if (val && integer_truep (val)
&& !(sameval_e && (sameval_e->flags & EDGE_DFS_BACK)))
{
@ -5947,7 +5964,7 @@ visit_phi (gimple *phi, bool *inserted, bool backedges_varying_p)
we can change sameval to def. */
if (EDGE_COUNT (bb->preds) == 2
&& (val = vn_nary_op_get_predicated_value
(vnresult, EDGE_PRED (bb, 0)->src))
(vnresult, EDGE_PRED (bb, 0)))
&& integer_truep (val)
&& !(e->flags & EDGE_DFS_BACK))
{