https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85598
--- Comment #12 from Jakub Jelinek <jakub at gcc dot gnu.org> --- (In reply to rguent...@suse.de from comment #11) > You need to union the PHI argument ranges. The result you can intersect > with the existing range info of the PHI result of course. You basically > want to do to the PHI what [E]VRP does ... If I were to recompute the range from scratch, yes, I would. The way it is written, it is able to optimize just the common case, where it uses the existing computed range and removes a single constant from the range, either the minimum or maximum, if it can prove the minimum (resp. maximum) will never occur. It does so by proving all PHI arguments but one are constants not equal to that value and one is from the edge where there is GIMPLE_COND comparison of the PHI arg SSA_NAME against that single constant. Now, I guess we could somewhat generalize it e.g. by accepting SSA_NAMEs with ranges instead of constants and just prove (perhaps through vr-values.h APIs) that the chosen constant is not in those ranges. > It's phiopt2 where this is important for the testcase? Or phiopt3 > after loop? Because after loop there's forwprop before and ccp > after phiopt both of which would be a better fit. Late CCP probably > doesn't need to be the SSA-propagator-iterating variant but could > do with a simpler DOM-style approach and thus could be replaced > by EVRP if it weren't for that lacking the alignment/nonzero bits > computation... For this testcase it needs to be done I believe in between dce2 (vrp1 does the jump threading and dce2 does the cleanup in which the PHI <0> is propagated into the PHI argument) and printf-return-value2 which needs it. In its current form it doesn't work in between cselim and dom2 because in between those passes (which include phiopt2) there is a forwarder block added and the code doesn't handle that (though, especially if it does the optimization from walking the PHIs rather than from the GIMPLE_COND) it could skip a single forwarder block too. SO, before cselim and in dom2 dump we have: <bb 3> [local count: 1063004407]: # RANGE [0, 256] NONZERO 511 # x_10 = PHI <0(2), x_5(3)> __builtin_snprintf (&temp, 4, "%%%02X", x_10); # RANGE [1, 256] NONZERO 511 x_5 = x_10 + 1; if (x_5 != 256) goto <bb 3>; [98.99%] else goto <bb 4>; [1.01%] which the patch can optimize, but in between those we have: <bb 3> [local count: 1063004407]: # RANGE [0, 256] NONZERO 511 # x_10 = PHI <0(2), x_5(5)> __builtin_snprintf (&temp, 4, "%%%02X", x_10); # RANGE [1, 256] NONZERO 511 x_5 = x_10 + 1; if (x_5 != 256) goto <bb 5>; [98.99%] else goto <bb 4>; [1.01%] <bb 5> [local count: 1052266994]: goto <bb 3>; [100.00%] which has the extra forwarder. So, on this testcase it is in the end optimized in phiopt3. There is forwprop3 in between those passes. > So I fear any "proper" solution isn't for stage3 but still I'd go > with factoring (enough of) vr_values::extract_range_from_phi_node > plus the register_edge_asserts thing if we need to look at > dominating conditions. Yes, I'm afraid this is just GCC 9 hack and I hope somebody (Aldy, Martin) will do the right thing for GCC 10 and this hack can be removed.