On 1/7/26 08:10, Richard Biener wrote:
On Tue, Jan 6, 2026 at 6:37 PM Andrew MacLeod <[email protected]> wrote:
VRP1 is allowed to remove a __builtin_unreachable () if it determines
that the other edge in the branch dominates all uses of all exports from
the block.
ie
<bb 3>:
x_8 = 1 << i_7;
if (x_8 <= 0) <<-- this is the branch in BB3
goto <bb 4>; [INV]
else
goto <bb 5>; [INV]
<bb 4> :
__builtin_unreachable ();
we can remove the branch and edge to bb 4 if we can prove that there
are no uses of x_8 or i_7 in or dominated by the edge 3->5. We can then
set the global ranges of i_7 and x_8 and move along.
This PR demonstrates that this normally works, but with rangers ability
to recompute values, we also have to look at the dependencies of all the
exports.
IN this case i_7 is defined:
<bb 7> :
# i_2 = PHI <i_7(5), n_4(D)(2), i_7(6)>
i_7 = i_2 + -1;
if (i_2 > 0)
goto <bb 3>; [INV]
else
goto <bb 8>; [INV]
so althoug the uses of i_7 Are dominated by 3->5, it does NOT dominate
the use of i_2 in bb_7. When early removal changes the global value of
i_7, ranger happily recomputes i_2 in the branch and decides that if i_7
is now [0, +INF], i_2 must always be > 0 and removes the branch.
Which is clearly incorrect. This patch teaches the early removal code
that it can only remove the unreachable call if x_8, i_7 and ALL the
dependencies used to calculate either name are ALL dominated by the
edge. This information is all trivially available in GORI, so its
noly a minor tweak.
Performance impact over a build of GCC is minimal. a 0.03% slowdown in VRP.
In the PR I mentioned not removing it if any of the dependencies had
more than a single use, but that turned out to be too limiting. This
solution works much better.
Bootstraps on x86_64-pc-linux-gnu with no regressions. OK?
OK. I'm somewhat concerned when I see
+ FOR_EACH_GORI_EXPORT_NAME (this, bb, name)
+ {
+ bitmap dep = get_def_chain (name);
+ if (dep)
+ bitmap_ior_into (tmpbit, dep);
in particular for pathological cases (ranger is nowadays involved at -O1 which
we recommend for such code). But we'll see.
Richard.
I did consider that, it is a potentially O(n^2) operation. This only
happens for blocks ending with a branch leading to a
__builtin_unreachable (), AND it can only happen during EVRP or VRP1.
That is the only time we attempt early unreachable removal, any other
use of ranger will not trigger this code.
Typically I wouldn't expect to see a lot of exports from blocks leading
to an unreachable, and typically those do not have large dependency
lists.. but of course there is always an exception :-P If we ever do
see an issue, or someone is sufficiently uncomfortable with it, we
could simply not do this under some threshold, or revert to a less
thorough litmus test.
Andrew