File 1193-beam_SUITE-Add-a-thorough-test-of-select_val.patch of Package erlang

From be2f940fd1d0b519be3731a09d6c6beb92f01c24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Wed, 21 Apr 2021 14:30:52 +0200
Subject: [PATCH] beam_SUITE: Add a thorough test of select_val

While at it, correct a type error for i_jump_on_val that would
cause an assertion to trigger in the DEBUG build.
---
 erts/emulator/beam/jit/x86/ops.tab |   2 +-
 erts/emulator/test/beam_SUITE.erl  | 117 ++++++++++++++++++++++++++---
 2 files changed, 107 insertions(+), 12 deletions(-)

diff --git a/erts/emulator/test/beam_SUITE.erl b/erts/emulator/test/beam_SUITE.erl
index b1f1e115ac..d76df2cff3 100644
--- a/erts/emulator/test/beam_SUITE.erl
+++ b/erts/emulator/test/beam_SUITE.erl
@@ -354,21 +354,116 @@ do_fconv(tuple_literal, Float) when is_float(Float) ->
     Float + {a,b}.
 
 select_val(Config) when is_list(Config) ->
-    zero = do_select_val(0),
-    big = do_select_val(1 bsl 64),
-    integer = do_select_val(42),
+    Mod = ?FUNCTION_NAME,
+
+    %% Test select_val instructions around interesting powers of 2.
+    Powers = lists:seq(0, 33) ++ lists:seq(47, 49) ++ lists:seq(58, 65),
+    L = make_tests(Powers, 0, []),
+    Code = make_module(Mod, L),
+    merl:compile_and_load(Code, []),
+
+    %% Uncomment the following line to print the generated code.
+    %%merl:print(Code),
+
+    verify(L, Mod),
+
+    %% Clean up.
+    true = code:delete(Mod),
+    false = code:purge(Mod),
+
     ok.
 
-do_select_val(X) ->
-    case X of
-	0 ->
-	    zero;
-	1 bsl 64 ->
-	    big;
-	Int when is_integer(Int) ->
-	    integer
+verify([{F,L}|T], Mod) ->
+    verify_1(L, F, Mod),
+
+    Sum = lists:sum([abs(V) || {V,_} <- L]),
+    expect_error(Mod, F, -Sum),
+    expect_error(Mod, F, Sum),
+    expect_error(Mod, F, not_an_integer),
+
+    verify(T, Mod);
+verify([], _Mod) -> ok.
+
+verify_1([{V,Exp}|T], F, Mod) ->
+    case Mod:F(V) of
+        Exp ->
+            verify_1(T, F, Mod);
+        Other ->
+            io:format("~p:~p(~p) evaluates to ~p; expected ~p",
+                      [Mod,F,V,Other,Exp]),
+            ct:fail(unexpected_value)
+    end;
+verify_1([], _, _) -> ok.
+
+expect_error(M, F, V) ->
+    try M:F(V) of
+        UnexpectedSuccess ->
+            io:format("~p:~p(~p) evaluates to ~p; expected it to fail",
+                      [M,F,V,UnexpectedSuccess]),
+            ct:fail(unexpected_success)
+    catch error:function_clause:Stk ->
+            [{M,F,[V],_}|_] = Stk
     end.
 
+make_tests([P|Ps], N0, Acc0) ->
+    {Acc,N} = make_tests_1(1 bsl P, N0, Acc0),
+    make_tests(Ps, N, Acc);
+make_tests([], N0, Acc0) ->
+    %% Finally, generate a function with a huge number of clauses.
+    NC = 2000,
+
+    %% Let the last number be a bignum.
+    Last = 1 bsl (erlang:system_info(wordsize)*8 - 5),
+
+    Step = 5,
+    {Acc,_} = make_test("huge_bsearch", Last - NC*Step, Last, Step, N0, Acc0),
+    lists:reverse(Acc).
+
+make_tests_1(V, N0, Acc0) ->
+    {Acc,N} = make_tests_2(V, N0, Acc0),
+    make_tests_2(-V, N, Acc).
+
+make_tests_2(V, N0, Acc0) ->
+    %% Because the values are not consecutive, a binary search will be
+    %% generated.
+    NumClauses = 14,
+    {Acc1,N1} = make_tests_3(V - NumClauses*5, V, NumClauses, 5, N0, Acc0),
+
+    %% Test a binary search with 107 values.
+    {Acc,N} = make_test("bsearch", V - 5*50, V + 5*56, 5, N1, Acc1),
+
+    %% Use consecutive values to allow a jump table to be used.
+    make_test("jump_tab", V - 10, V + 10, 1, N, Acc).
+
+make_tests_3(_First, _Last, 0, _Step, N, Acc) ->
+    {Acc,N};
+make_tests_3(First, Last, NumClauses, Step, N0, Acc0) ->
+    {Acc,N} = make_test("f", First, Last, Step, N0, Acc0),
+    make_tests_3(First+Step, Last+Step, NumClauses-1, Step, N, Acc).
+
+make_test(Prefix, First, Last, Step, N, Acc) ->
+    Name = list_to_atom(Prefix ++ integer_to_list(N)),
+    Seq = lists:seq(First, Last, Step),
+    L = [{I,erlang:phash2({I,N})} || I <- Seq],
+    {[{Name,L}|Acc],N+1}.
+
+make_module(Mod, L) ->
+    ModDef = ?Q(["-module('@Mod@')."]),
+    Fs = make_funcs(L),
+    Xs = [{F,1} || {F,_} <- L],
+    Exported = [erl_syntax:arity_qualifier(merl:term(N), merl:term(A)) ||
+                   {N,A} <- Xs],
+    Export = ?Q("-export(['@_Exported'/1])."),
+    [ModDef, Export | Fs].
+
+make_funcs([{Name,List}|T]) ->
+    [make_func(Name, List) | make_funcs(T)];
+make_funcs([]) -> [].
+
+make_func(Name, List) ->
+    Cs = [?Q(["(_@I@) -> _@Body@"]) || {I,Body} <- List],
+    erl_syntax:function(erl_syntax:atom(Name), Cs).
+
 swap_temp_apply(_Config) ->
     {swap_temp_applied,42} = do_swap_temp_apply(41),
     not_an_integer = do_swap_temp_apply(not_an_integer),
-- 
2.26.2

openSUSE Build Service is sponsored by