diff --git a/erts/emulator/test/small_SUITE.erl b/erts/emulator/test/small_SUITE.erl index aa732c1e24d9..21cbf6135cb8 100644 --- a/erts/emulator/test/small_SUITE.erl +++ b/erts/emulator/test/small_SUITE.erl @@ -860,6 +860,22 @@ gen_div_function({Name,{A,B}}) -> put(prevent_div_rem_fusion, Q), R = X rem Y, {Q, R}; + '@Name@'(any0, fixed, Y) -> + X = _@A@, + Q = X div Y, + R = X rem Y, + {Q, R}; + '@Name@'(any1, fixed, Y) -> + X = _@A@, + R = X rem Y, + Q = X div Y, + {Q, R}; + '@Name@'(any2, fixed, Y) -> + X = _@A@, + Q = X div Y, + put(prevent_div_rem_fusion, Q), + R = X rem Y, + {Q, R}; '@Name@'(X0, Y0, integer0) -> Q = X0 div Y0, R = X0 rem Y0, @@ -945,6 +961,22 @@ gen_div_function({Name,{A,B}}) -> Q = X div Y, put(prevent_div_rem_fusion, Q), R = X rem Y, + {Q, R}; + '@Name@'(fixed, Y, any0) -> + X = _@A@, + Q = X div Y, + R = X rem Y, + {Q, R}; + '@Name@'(fixed, Y, any1) -> + X = _@A@, + R = X rem Y, + Q = X div Y, + {Q, R}; + '@Name@'(fixed, Y, any2) -> + X = _@A@, + Q = X div Y, + put(prevent_div_rem_fusion, Q), + R = X rem Y, {Q, R}. "). @@ -969,6 +1001,9 @@ test_division([{Name,{A,B}}|T], Mod) -> PosRes = F(any0, A, fixed), PosRes = F(any1, A, fixed), PosRes = F(any2, A, fixed), + PosRes = F(any0, fixed, B), + PosRes = F(any1, fixed, B), + PosRes = F(any2, fixed, B), PosRes = F(A, B, integer0), PosRes = F(A, fixed, integer1), @@ -985,6 +1020,9 @@ test_division([{Name,{A,B}}|T], Mod) -> PosRes = F(A, fixed, any0), PosRes = F(A, fixed, any1), PosRes = F(A, fixed, any2), + PosRes = F(fixed, B, any0), + PosRes = F(fixed, B, any1), + PosRes = F(fixed, B, any2), NegRes = F(integer0, -A, B), NegRes = F(integer1, -A, fixed), diff --git a/lib/compiler/src/beam_bounds.erl b/lib/compiler/src/beam_bounds.erl index cfa6e4d37877..5c1b42745f2f 100644 --- a/lib/compiler/src/beam_bounds.erl +++ b/lib/compiler/src/beam_bounds.erl @@ -327,8 +327,11 @@ 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}; + %% is the range of the left-hand side operand extended to always + %% include zero. + Min = inf_min(0, A), + Max = inf_max(0, B), + normalize({Min,Max}); rem_bounds(_, _) -> any. diff --git a/lib/compiler/test/beam_bounds_SUITE.erl b/lib/compiler/test/beam_bounds_SUITE.erl index bee79533b9c1..d5c27d0bdf3d 100644 --- a/lib/compiler/test/beam_bounds_SUITE.erl +++ b/lib/compiler/test/beam_bounds_SUITE.erl @@ -133,6 +133,9 @@ division_bounds(_Config) -> {-50,50} = beam_bounds:bounds('div', {-50,-15}, {-10,'+inf'}), {-20,20} = beam_bounds:bounds('div', {-20,10}, any), {-7,7} = beam_bounds:bounds('div', {-5,7}, {'-inf',-1}), + {-42,42} = beam_bounds:bounds('div', {42,42}, any), + {-42,42} = beam_bounds:bounds('div', {-42,-42}, any), + any = beam_bounds:bounds('div', {'-inf',10}, any), any = beam_bounds:bounds('div', {0,'+inf'}, any), @@ -153,15 +156,26 @@ rem_bounds(_Config) -> {-7,7} = beam_bounds:bounds('rem', {'-inf',10}, {1,8}), {0,7} = beam_bounds:bounds('rem', {10,'+inf'}, {1,8}), + {0,'+inf'} = beam_bounds:bounds('rem', {17,'+inf'}, any), - {1,10} = beam_bounds:bounds('rem', {1,10}, {'-inf',10}), - {20,'+inf'} = beam_bounds:bounds('rem', {20,'+inf'}, {10,'+inf'}), + {0,10} = beam_bounds:bounds('rem', {1,10}, {'-inf',10}), + {0,'+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'}), + {-11,10} = beam_bounds:bounds('rem', {-11,10}, any), + + {0,0} = beam_bounds:bounds('rem', {0,0}, any), + {0,1} = beam_bounds:bounds('rem', {1,1}, any), + {0,2} = beam_bounds:bounds('rem', {2,2}, any), + {0,3} = beam_bounds:bounds('rem', {2,3}, any), + + {-1,0} = beam_bounds:bounds('rem', {-1,-1}, any), + {-7,0} = beam_bounds:bounds('rem', {-7,-7}, any), + {-6,0} = beam_bounds:bounds('rem', {-6,-4}, any), ok.