https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84515
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |law at gcc dot gnu.org, | |rguenth at gcc dot gnu.org --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Note we don't do loop merging here but final value replacement does it's job. What is missing is jump-threading the two loop header copy checks count/2 != 0 and i < count if that is easily possible. So we end up with if (count/2 != 0) g += count/2; # tem = PHI <count/2, 0> if (count > tem) g += count - tem; those loop header checks also stand in the way of loop fusion (well, it's not classical fusion given the different iteration spaces). Not sure why DOM doesn't consider threading the above. Eventually it's a very special phiopt opportunity as well (but late phiopt runs too late). <bb 2> [local count: 118111601]: _20 = count_11(D) >> 1; if (_20 != 0) goto <bb 3>; [89.00%] else goto <bb 4>; [11.00%] <bb 3> [local count: 105119325]: <bb 4> [local count: 118111600]: # i_22 = PHI <_20(3), 0(2)> if (count_11(D) > i_22) note phiopt already does PHI i_22 reduced for COND_EXPR in block 2 to _20. so we end up with <bb 4> [local count: 118111600]: # i_22 = PHI <_20(3), _20(2)> if (count_11(D) > i_22) goto <bb 5>; [89.00%] but nothing simplifies it further on GIMPLE. Note that of course count_11(D) > count_11(D) >> 1 isn't always true.