summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2023-04-25 17:08:52 +0200
committerErlang/OTP <otp@erlang.org>2023-04-25 17:08:52 +0200
commitec59a080681865a8a32003ec527b6802e8aefdc5 (patch)
tree3d6fa69af031753c0190f39c9cdab5f14152ad9f
parente597996dded611ed8b07a29e666599818607fc12 (diff)
parentc62f3fabe2ee9ca610f1fc9605181b06f820c31c (diff)
downloaderlang-ec59a080681865a8a32003ec527b6802e8aefdc5.tar.gz
Merge branch 'john/erts/fix-hd-tl-loader-transformations/GH-7024/OTP-18519' into maint-25
* john/erts/fix-hd-tl-loader-transformations/GH-7024/OTP-18519: jit: Fix hd/1 and tl/1 BIF specialization
-rw-r--r--erts/emulator/beam/jit/arm/ops.tab8
-rw-r--r--erts/emulator/beam/jit/x86/instr_guard_bifs.cpp24
-rw-r--r--erts/emulator/beam/jit/x86/ops.tab14
-rw-r--r--lib/compiler/test/bif_SUITE.erl28
4 files changed, 44 insertions, 30 deletions
diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab
index cc0bfeccf0..9cfce18e58 100644
--- a/erts/emulator/beam/jit/arm/ops.tab
+++ b/erts/emulator/beam/jit/arm/ops.tab
@@ -666,18 +666,14 @@ i_perf_counter
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=n Dst =>
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src Dst =>
+bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_hd Src Dst
bif1 Fail=p Bif=u$bif:erlang:hd/1 Src Dst =>
bif_hd Src Dst
bif_hd s d
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=n Dst =>
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src Dst =>
+bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_tl Src Dst
bif1 Fail=p Bif=u$bif:erlang:tl/1 Src Dst =>
bif_tl Src Dst
diff --git a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
index 4dfe39cb98..26133d5ac0 100644
--- a/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
+++ b/erts/emulator/beam/jit/x86/instr_guard_bifs.cpp
@@ -60,24 +60,22 @@ void BeamGlobalAssembler::emit_handle_hd_error() {
* The code size for this specialization of hd/1 is 21 bytes,
* while the code size for the bif1 instruction is 24 bytes.
*/
-void BeamModuleAssembler::emit_bif_hd(const ArgLabel &Fail,
- const ArgSource &Src,
+void BeamModuleAssembler::emit_bif_hd(const ArgSource &Src,
const ArgRegister &Hd) {
+ Label good_cons = a.newLabel();
+
mov_arg(RET, Src);
a.test(RETb, imm(_TAG_PRIMARY_MASK - TAG_PRIMARY_LIST));
- if (Fail.get() != 0) {
- a.jne(resolve_beam_label(Fail));
- } else {
- Label next = a.newLabel();
- a.short_().je(next);
- safe_fragment_call(ga->get_handle_hd_error());
- a.bind(next);
- }
+ a.short_().je(good_cons);
+ safe_fragment_call(ga->get_handle_hd_error());
- x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
- a.mov(ARG2, getCARRef(boxed_ptr));
- mov_arg(Hd, ARG2);
+ a.bind(good_cons);
+ {
+ x86::Gp boxed_ptr = emit_ptr_val(RET, RET);
+ a.mov(ARG2, getCARRef(boxed_ptr));
+ mov_arg(Hd, ARG2);
+ }
}
void BeamGlobalAssembler::emit_handle_element_error() {
diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab
index 1ce0d6f9c2..5481fff2d8 100644
--- a/erts/emulator/beam/jit/x86/ops.tab
+++ b/erts/emulator/beam/jit/x86/ops.tab
@@ -660,18 +660,14 @@ i_perf_counter
bif0 u$bif:erlang:self/0 Dst=d => self Dst
bif0 u$bif:erlang:node/0 Dst=d => node Dst
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=n Dst =>
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:hd/1 Src Dst =>
+bif1 Fail=f Bif=u$bif:erlang:hd/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_hd Src Dst
-bif1 Fail Bif=u$bif:erlang:hd/1 Src Dst =>
- bif_hd Fail Src Dst
+bif1 Fail=p Bif=u$bif:erlang:hd/1 Src Dst =>
+ bif_hd Src Dst
-bif_hd j s d
+bif_hd s d
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=n Dst =>
- jump Fail
-bif1 Fail=f Bif=u$bif:erlang:tl/1 Src Dst =>
+bif1 Fail=f Bif=u$bif:erlang:tl/1 Src=xy Dst =>
is_nonempty_list Fail Src | get_tl Src Dst
bif1 Fail Bif=u$bif:erlang:get/1 Src=s Dst=d => get(Src, Dst)
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index 8480569507..34bf54a871 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -24,7 +24,8 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
beam_validator/1,trunc_and_friends/1,cover_safe_and_pure_bifs/1,
- cover_trim/1]).
+ cover_trim/1,
+ head_tail/1]).
suite() ->
[{ct_hooks,[ts_install_cth]}].
@@ -37,7 +38,8 @@ groups() ->
[beam_validator,
trunc_and_friends,
cover_safe_and_pure_bifs,
- cover_trim
+ cover_trim,
+ head_tail
]}].
init_per_suite(Config) ->
@@ -167,6 +169,28 @@ cover_trim_3(Header, N)->
false
end.
+%% GH-7024: The loader transformations for hd/1 and tl/1 were incorrect and
+%% failed when certain optimizations were turned off.
+head_tail(_Config) ->
+ {1, ok} = head_case(),
+ {1, ok} = tail_case(),
+
+ 1 = hd(id([1])),
+ [] = tl(id([1])),
+
+ ok.
+
+head_case() ->
+ case 1 of
+ X when hd(X) -> blurf;
+ X -> {X, ok}
+ end.
+
+tail_case() ->
+ case 1 of
+ X when tl(X) -> blurf;
+ X -> {X, ok}
+ end.
id(I) ->
I.