tree-optimization/107876 - unswitching of switch

The following shows a missed update of dominators when unswitching
removes unreachable edges from switch stmts it unswitches.  Fixed
by wiping dominator info in that case.

	PR tree-optimization/107876
	* tree-ssa-loop-unswitch.cc (clean_up_after_unswitching): Wipe
	dominator info if we removed an edge.

	* g++.dg/tree-ssa/pr107876.C: New testcase.
This commit is contained in:
Richard Biener 2022-11-28 09:19:33 +01:00
parent 0976b012d8
commit 238cf114de
2 changed files with 47 additions and 1 deletions

View File

@ -0,0 +1,38 @@
// { dg-do compile }
// { dg-require-effective-target c++11 }
// { dg-options "-O2 -funswitch-loops --param max-unswitch-insns=5 -fdump-tree-unswitch-details" }
class X {
public:
X();
X(const X&);
X(const volatile X &);
~X();
};
X test17(int i) {
if (false) {
impossible:
if (i == 3)
return X();
}
while (true) {
X x;
if (i == 0)
return x;
if (i == 1)
break;
if (i == 2)
continue;
if (i == 3)
goto impossible;
if (i == 4)
__builtin_exit(1);
if (i == 5)
return x;
}
return X();
}
// { dg-final { scan-tree-dump "unswitching loop 1 on .switch. with condition: i_\[0-9\]+\\(D\\) == 2" "unswitch" } }

View File

@ -1631,6 +1631,7 @@ clean_up_after_unswitching (int ignored_edge_flag)
basic_block bb;
edge e;
edge_iterator ei;
bool removed_edge = false;
FOR_EACH_BB_FN (bb, cfun)
{
@ -1655,7 +1656,10 @@ clean_up_after_unswitching (int ignored_edge_flag)
to preserve its edge. But we can remove the
non-default CASE sharing the edge. */
if (e != default_e)
remove_edge (e);
{
remove_edge (e);
removed_edge = true;
}
}
else
{
@ -1672,6 +1676,10 @@ clean_up_after_unswitching (int ignored_edge_flag)
FOR_EACH_EDGE (e, ei, bb->succs)
e->flags &= ~ignored_edge_flag;
}
/* If we removed an edge we possibly have to recompute dominators. */
if (removed_edge)
free_dominance_info (CDI_DOMINATORS);
}
/* Loop unswitching pass. */