File 3133-Enhance-range-analysis-for-the-rem-operator.patch of Package erlang
From acf3116e55f2381f815944e5d69012a8eed432a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Sun, 13 Aug 2023 09:33:15 +0200
Subject: [PATCH 3/6] Enhance range analysis for the rem operator
Teach beam_bounds:bound/3 to determine a range for the `rem` operator
when nothing is known about the right-hand side operand. For example:
rem0(A, B) when is_integer(A), 0 =< A, A < 1204 ->
%% Range for A is 0..1023
A rem B. % Range is 0..1023 (same as for A)
---
lib/compiler/src/beam_bounds.erl | 6 ++++++
lib/compiler/test/beam_bounds_SUITE.erl | 13 ++++++++-----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl
index 95a222cf9d..59b7f27c86 100644
--- a/lib/compiler/src/beam_bounds.erl
+++ b/lib/compiler/src/beam_bounds.erl
@@ -319,6 +319,12 @@ rem_bounds(_, {C,D}) when is_integer(C), is_integer(D),
Max = max(abs(C), abs(D)) - 1,
Min = -Max,
normalize({Min,Max});
+rem_bounds({A,B}, _) ->
+ %% The sign of the remainder is the same as the sign of the
+ %% left-hand side operand; it does not depend on the sign of the
+ %% right-hand side operand. Therefore, the range of the remainder
+ %% is the same as the range of the left-hand side operand.
+ {A,B};
rem_bounds(_, _) ->
any.
diff --git a/lib/compiler/test/beam_bounds_SUITE.erl b/lib/compiler/test/beam_bounds_SUITE.erl
index 33f216548d..42a8add3d7 100644
--- a/lib/compiler/test/beam_bounds_SUITE.erl
+++ b/lib/compiler/test/beam_bounds_SUITE.erl
@@ -154,11 +154,14 @@ rem_bounds(_Config) ->
{-7,7} = beam_bounds:bounds('rem', {'-inf',10}, {1,8}),
{0,7} = beam_bounds:bounds('rem', {10,'+inf'}, {1,8}),
- any = beam_bounds:bounds('rem', {1,10}, {'-inf',10}),
- any = beam_bounds:bounds('rem', {1,10}, {10,'+inf'}),
-
- any = beam_bounds:bounds('rem', {-10,10}, {'-inf',10}),
- any = beam_bounds:bounds('rem', {-10,10}, {10,'+inf'}),
+ {1,10} = beam_bounds:bounds('rem', {1,10}, {'-inf',10}),
+ {20,'+inf'} = beam_bounds:bounds('rem', {20,'+inf'}, {10,'+inf'}),
+ {'-inf',10} = beam_bounds:bounds('rem', {'-inf',10}, any),
+
+ {-11,10} = beam_bounds:bounds('rem', {-11,10}, {'-inf',89}),
+ {-11,10} = beam_bounds:bounds('rem', {-11,10}, {7,'+inf'}),
+ {-11,10} = beam_bounds:bounds('rem', {-11,10}, {'-inf',113}),
+ {-11,10} = beam_bounds:bounds('rem', {-11,10}, {55,'+inf'}),
ok.
--
2.35.3