diff options
| author | John Högberg <john@erlang.org> | 2023-04-24 14:12:15 +0200 |
|---|---|---|
| committer | John Högberg <john@erlang.org> | 2023-04-24 16:00:17 +0200 |
| commit | 8e5b1fbb16d186eb620e4df3470c9cba99885afc (patch) | |
| tree | 00076728ece7641764c02f0c6c045b6a6b0ac689 /lib/compiler/src | |
| parent | 039c5deb0d1a1561d6ecd74b8e5e637cff303d6e (diff) | |
| download | erlang-8e5b1fbb16d186eb620e4df3470c9cba99885afc.tar.gz | |
beam_bounds: Make 'bnot' converge faster
Fixes #7145
Diffstat (limited to 'lib/compiler/src')
| -rw-r--r-- | lib/compiler/src/beam_bounds.erl | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl index 6f3902596e..6ac5141821 100644 --- a/lib/compiler/src/beam_bounds.erl +++ b/lib/compiler/src/beam_bounds.erl @@ -46,7 +46,28 @@ bounds('bnot', R0) -> case R0 of - {A,B} -> + {A, B} when is_integer(A), is_integer(B), A =/= B -> + %% While it's easy to get an exact range, doing so can make certain + %% chains of operations slow to converge, e.g. + %% + %% f(0) -> -1; f(N) -> abs(bnot f(N)). + %% + %% Where the range increases by 1 every time we pass through, + %% making it more or less impossible to reach a fixpoint. + %% + %% We therefore widen the range a bit quicker to ensure that we + %% converge on 'any' within a reasonable time frame, hoping that + %% the range will still be tight enough in the cases where we + %% don't feed the result into itself. + case {abs(A) bsr ?NUM_BITS, abs(B) bsr ?NUM_BITS} of + {0, 0} -> + Min = min(-B - 1, -(B bsl 1) - 1), + Max = max(-A - 1, -(A bsl 1) - 1), + normalize({Min, Max}); + {_, _} -> + any + end; + {A, B} -> R = {inf_add(inf_neg(B), -1), inf_add(inf_neg(A), -1)}, normalize(R); _ -> |
