Skip to content

Commit

Permalink
Enhance range analysis for the rem operator
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
bjorng committed Aug 15, 2023
1 parent ad264fc commit acf3116
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
6 changes: 6 additions & 0 deletions lib/compiler/src/beam_bounds.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
13 changes: 8 additions & 5 deletions lib/compiler/test/beam_bounds_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit acf3116

Please sign in to comment.