https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69991
Bug ID: 69991 Summary: missed tail merge optimization Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: vries at gcc dot gnu.org Target Milestone: --- Consider testcase test.c: ... void foo (int c, int d, int *z, int *y) { int res = 0; if (c) { *y = 0; if (d) { *z = 1; res = *y; } } else { *z = 1; res = *y; } } ... When compiled with -O2 -fno-tree-dce, tail-merge fails, due to this check in find_duplicate: ... /* If the incoming vuses are not the same, and the vuse escaped into an SSA_OP_DEF, then merging the 2 blocks will change the value of the def, which potentially means the semantics of one of the blocks will be changed. TODO: make this check more precise. */ if (vuse_escaped && vuse1 != vuse2) return; ... Removing the check allows the testcase to be tail-merged, and the testcase belonging the check (pr52734.c) still passes. This is due to the fix for PR62167. With a less conservative fix for PR62167, we'd still need this check for pr52734.c. So it's not necessarily a good idea to remove the check now. A quick fix would be to ignore defs with no uses in gsi_advance_bw_nondebug_nonlocal, in the same way we ignore stmts with zero operands. But the usability of such a fix would be limited. Another option is to consider the TODO mentioned in the comment. The test-case pr52734.c can actually safely be tail-merged, as long as the right bb is chosen. If we can model the incoming vuse as a dependency for one bb, we should be able to choose the right bb (the empty one with no depencencies).