File 2911-Strengthen-tests-of-relational-operators.patch of Package erlang
From cc712e241005c08d81b6d980fa477011c29b0b88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Wed, 27 Apr 2022 07:00:30 +0200
Subject: [PATCH] Strengthen tests of relational operators
Strengthen tests of relational operators to better test current
and potential future optimizations done by the JIT.
---
erts/emulator/test/op_SUITE.erl | 255 ++++++++++++++++++++++++++++--
lib/compiler/test/guard_SUITE.erl | 29 +++-
2 files changed, 269 insertions(+), 15 deletions(-)
diff --git a/erts/emulator/test/op_SUITE.erl b/erts/emulator/test/op_SUITE.erl
index 8353bae15e..fa03262f09 100644
--- a/erts/emulator/test/op_SUITE.erl
+++ b/erts/emulator/test/op_SUITE.erl
@@ -23,18 +23,19 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0, suite/0,
- bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,complex_relop/1]).
+ bsl_bsr/1,logical/1,t_not/1,relop_simple/1,relop/1,
+ complex_relop/1,
+ range_tests/1]).
--export([]).
-import(lists, [foldl/3,flatmap/2]).
suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap, {minutes, 5}}].
-all() ->
+all() ->
[bsl_bsr, logical, t_not, relop_simple, relop,
- complex_relop].
+ complex_relop, range_tests].
%% Test the bsl and bsr operators.
bsl_bsr(Config) when is_list(Config) ->
@@ -334,18 +334,25 @@ run_test_module(Cases, GuardsOk) ->
Module = erl_parse:new_anno(Module0),
lists:foreach(fun(F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Module),
- %% Compile, load, and run the generated module.
+ %% Compile, load, and run the generated module. Test both with and
+ %% without compiler optimizations to ensure that we test both the
+ %% implementation of the BIFs and the BEAM instructions.
+ do_run_test_module(Module, []),
+ do_run_test_module(Module, [no_copt,no_ssa_opt,no_postopt]).
+
+do_run_test_module(Module, Opts) ->
+ {ok,Mod,Code1} = compile:forms(Module, [time|Opts]),
+ _ = code:delete(Mod),
+ _ = code:purge(Mod),
- {ok,Mod,Code1} = compile:forms(Module, [time]),
- code:delete(Mod),
- code:purge(Mod),
{module,Mod} = code:load_binary(Mod, Mod, Code1),
+
run_function(Mod, guard_tests),
run_function(Mod, body_tests),
run_function(Mod, bif_tests),
true = code:delete(Mod),
- code:purge(Mod),
+ _ = code:purge(Mod),
ok.
@@ -424,6 +432,236 @@ eval(E0) ->
{value,Val,_Bs} -> Val
end.
+range_tests(_Config) ->
+ %% Define the limits for smalls on a 64-bit system.
+ {MinSmall, MaxSmall} = {-1 bsl 59, (1 bsl 59) - 1},
+ case erlang:system_info(wordsize) of
+ 8 ->
+ %% Assertions.
+ 2 = erts_debug:flat_size(MinSmall-1),
+ 0 = erts_debug:flat_size(MinSmall),
+ 0 = erts_debug:flat_size(MaxSmall),
+ 2 = erts_debug:flat_size(MaxSmall+1);
+ 4 ->
+ ok
+ end,
+
+ lesser = range(-1 bsl 64),
+ lesser = range(MinSmall),
+ lesser = range(0),
+ lesser = range(-1),
+ lesser = range(0.9999),
+
+ inside = range_any(1),
+ inside = range_any(2),
+ inside = range_any(2.5),
+ inside = range_any(math:pi()),
+ inside = range_any(5),
+ inside = range_any(9),
+ inside = range_any(10),
+
+ greater = range(10.0001),
+ greater = range(11),
+ greater = range(MaxSmall),
+ greater = range(1 bsl 64),
+ greater = range(atom),
+ greater = range(self()),
+ greater = range(make_ref()),
+ greater = range({a,b}),
+ greater = range([a,b]),
+ greater = range([]),
+ greater = range(<<1,2,3>>),
+ greater = range(fun() -> ok end),
+ greater = range(fun ?MODULE:range_tests/1),
+
+ lesser = range(-1 bsl 64),
+ lesser = range(float(-1 bsl 64)),
+ lesser = range_big(MinSmall - 2),
+ lesser = range_barely_small(MinSmall - 1),
+
+ inside = range_barely_small(MinSmall),
+ inside = range_barely_small(-1 bsl 58),
+ inside = range_barely_small(0),
+ inside = range_barely_small(17.75),
+ inside = range_barely_small(1 bsl 58),
+ inside = range_barely_small(MaxSmall),
+
+ greater = range_barely_small(MaxSmall + 1),
+ greater = range_big(MaxSmall + 2),
+ greater = range_big(1 bsl 64),
+ greater = range_big(float(1 bsl 64)),
+
+ lesser = range(-1 bsl 64),
+ lesser = range(float(-1 bsl 64)),
+ lesser = range_big(MinSmall - 2),
+
+ inside = range_big(MinSmall),
+ inside = range_big(-1 bsl 58),
+ inside = range_big(0),
+ inside = range_barely_small(17.75),
+ inside = range_big(1 bsl 58),
+ inside = range_big(MaxSmall),
+
+ greater = range_big(MaxSmall + 2),
+ greater = range_big(1 bsl 64),
+ greater = range_big(float(1 bsl 64)),
+
+ ok.
+
+range(X) ->
+ Res = range_any(X),
+ if
+ is_integer(X) ->
+ Res = range_any(float(X)),
+ Res = range_number(X),
+ Res = range_number(float(X)),
+ Res = range_int(X),
+ if
+ X =:= X band 16#ffff ->
+ Res = range_small_int(X);
+ true ->
+ Res
+ end;
+ is_number(X) ->
+ Res = range_number(X);
+ true ->
+ Res = range_big(X),
+ Res = range_barely_small(X)
+ end.
+
+range_any(X0) ->
+ X = id(X0),
+ case range_any_1(X) of
+ inside ->
+ inside = range_any_2(X);
+ Other ->
+ outside = range_any_2(X),
+ Other
+ end.
+
+%% The guard tests have different failure labels.
+range_any_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_any_1(X) when X < 1 ->
+ lesser;
+range_any_1(X) when X > 10 ->
+ greater.
+
+%% The guard tests have the same failure label.
+range_any_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_any_2(_) ->
+ outside.
+
+range_number(X) when is_number(X) ->
+ case range_number_1(X) of
+ inside ->
+ inside = range_number_2(X);
+ Other ->
+ outside = range_number_2(X),
+ Other
+ end.
+
+range_number_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_number_1(X) when X < 1 ->
+ lesser;
+range_number_1(X) when X > 10 ->
+ greater.
+
+range_number_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_number_2(_) ->
+ outside.
+
+range_int(X) when is_integer(X) ->
+ case range_int_1(X) of
+ inside ->
+ inside = range_int_2(X);
+ Other ->
+ outside = range_int_2(X),
+ Other
+ end.
+
+range_int_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_int_1(X) when X < 1 ->
+ lesser;
+range_int_1(X) when X > 10 ->
+ greater.
+
+range_int_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_int_2(_) ->
+ outside.
+
+range_small_int(X) when is_integer(X) ->
+ case range_small_int_1(X) of
+ inside ->
+ inside = range_small_int_2(X);
+ Other ->
+ outside = range_small_int_2(X),
+ Other
+ end.
+
+range_small_int_1(X) when 1 =< X, X =< 10 ->
+ inside;
+range_small_int_1(X) when X < 1 ->
+ lesser;
+range_small_int_1(X) when X > 10 ->
+ greater.
+
+range_small_int_2(X) when 1 =< X, X =< 10 ->
+ inside;
+range_small_int_2(_) ->
+ outside.
+
+range_barely_small(X) ->
+ case range_barely_small_1(X) of
+ inside ->
+ inside = range_barely_small_2(X);
+ Other ->
+ outside = range_barely_small_2(X),
+ Other
+ end.
+
+range_barely_small_1(X) when -1 bsl 59 =< X, X =< (1 bsl 59) - 1 ->
+ inside;
+range_barely_small_1(X) when X < -1 bsl 59 ->
+ lesser;
+range_barely_small_1(X) when X > (1 bsl 59) - 1 ->
+ greater.
+
+range_barely_small_2(X) when -1 bsl 59 =< X, X =< (1 bsl 59) - 1 ->
+ inside;
+range_barely_small_2(_) ->
+ outside.
+
+range_big(X) ->
+ case range_big_1(X) of
+ inside ->
+ inside = range_big_2(X);
+ Other ->
+ outside = range_big_2(X),
+ Other
+ end.
+
+range_big_1(X) when (-1 bsl 59) - 1 =< X, X =< 1 bsl 59 ->
+ inside;
+range_big_1(X) when X < (-1 bsl 59) - 1 ->
+ lesser;
+range_big_1(X) when X > 1 bsl 59 ->
+ greater.
+
+range_big_2(X) when (-1 bsl 59) - 1 =< X, X =< 1 bsl 59 ->
+ inside;
+range_big_2(_) ->
+ outside.
+
+%%%
+%%% Utilities.
+%%%
+
unvalue(V) ->
Abstr = erl_parse:abstract(V),
erl_parse:anno_to_term(Abstr).
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 5a4d8d1e80..ba89255e7b 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1435,16 +1435,24 @@ rel_op_combinations(Config) when is_list(Config) ->
lists:seq(16#06F0, 16#06F9),
Digits = gb_sets:from_list(Digits0),
rel_op_combinations_1(16#0700, Digits),
+ false = is_digit(-1 bsl 59),
+ false = is_digit(-1 bsl 64),
+ false = is_digit((1 bsl 59) - 1),
+ false = is_digit(1 bsl 64),
BrokenRange0 = lists:seq(3, 5) ++
lists:seq(10, 12) ++ lists:seq(14, 20),
BrokenRange = gb_sets:from_list(BrokenRange0),
rel_op_combinations_2(30, BrokenRange),
+ false = broken_range(-1 bsl 64),
+ false = broken_range(1 bsl 64),
Red0 = [{I,2*I} || I <- lists:seq(0, 50)] ++
[{I,5*I} || I <- lists:seq(51, 80)],
Red = gb_trees:from_orddict(Red0),
rel_op_combinations_3(100, Red),
+ 2 * (-1 bsl 64) = redundant(-1 bsl 64),
+ none = redundant(1 bsl 64),
rel_op_combinations_4(),
@@ -1454,6 +1462,10 @@ rel_op_combinations_1(0, _) ->
ok;
rel_op_combinations_1(N, Digits) ->
Bool = gb_sets:is_member(N, Digits),
+ Bool = is_digit(N),
+ rel_op_combinations_1(N-1, Digits).
+
+is_digit(N) ->
Bool = is_digit_1(N),
Bool = is_digit_2(N),
Bool = is_digit_3(N),
@@ -1464,8 +1476,7 @@ rel_op_combinations_1(N, Digits) ->
Bool = is_digit_8(N),
Bool = is_digit_9(42, N),
Bool = is_digit_10(N, 0),
- Bool = is_digit_11(N, 0),
- rel_op_combinations_1(N-1, Digits).
+ Bool = is_digit_11(N, 0).
is_digit_1(X) when 16#0660 =< X, X =< 16#0669 -> true;
is_digit_1(X) when 16#0030 =< X, X =< 16#0039 -> true;
@@ -1530,6 +1541,10 @@ rel_op_combinations_2(0, _) ->
ok;
rel_op_combinations_2(N, Range) ->
Bool = gb_sets:is_member(N, Range),
+ Bool = broken_range(N),
+ rel_op_combinations_2(N-1, Range).
+
+broken_range(N) ->
Bool = broken_range_1(N),
Bool = broken_range_2(N),
Bool = broken_range_3(N),
@@ -1542,8 +1557,7 @@ rel_op_combinations_2(N, Range) ->
Bool = broken_range_10(N),
Bool = broken_range_11(N),
Bool = broken_range_12(N),
- Bool = broken_range_13(N),
- rel_op_combinations_2(N-1, Range).
+ Bool = broken_range_13(N).
broken_range_1(X) when X >= 10, X =< 20, X =/= 13 -> true;
broken_range_1(X) when X >= 3, X =< 5 -> true;
@@ -1615,6 +1629,10 @@ rel_op_combinations_3(N, Red) ->
none -> none;
{value,V} -> V
end,
+ Val = redundant(N),
+ rel_op_combinations_3(N-1, Red).
+
+redundant(N) ->
Val = redundant_1(N),
Val = redundant_2(N),
Val = redundant_3(N),
@@ -1626,8 +1644,7 @@ rel_op_combinations_3(N, Red) ->
Val = redundant_9(N),
Val = redundant_10(N),
Val = redundant_11(N),
- Val = redundant_12(N),
- rel_op_combinations_3(N-1, Red).
+ Val = redundant_12(N).
redundant_1(X) when X >= 51, X =< 80 -> 5*X;
redundant_1(X) when X < 51 -> 2*X;
--
2.34.1