From 6f872f0a7436c4dbb7a719033bb6f84068d3b639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 28 Jun 2024 12:24:30 +0200 Subject: [PATCH] Remove special handling of bs_skip_bits2 for literal sizes Starting from Erlang/OTP 26, the `bs_skip_bits2` instruction will almost never have a literal size in optimized (skip instructions with literal sizes will usually be part of a `bs_match` instruction). Therefore, there is no longer any point in handling literal sizes specially. Note that there was special handling of operands of `bs_skip_bits2` last emitted by Erlang/OTP 18. This is no longer necessary because the loader will refuse to load any module compiled by Erlang/OTP 22 or earlier. --- erts/emulator/beam/emu/bs_instrs.tab | 11 ----- erts/emulator/beam/emu/ops.tab | 12 +++-- erts/emulator/beam/generators.tab | 66 ------------------------- erts/emulator/beam/jit/arm/instr_bs.cpp | 7 --- erts/emulator/beam/jit/arm/ops.tab | 12 +++-- erts/emulator/beam/jit/x86/instr_bs.cpp | 8 --- erts/emulator/beam/jit/x86/ops.tab | 12 +++-- 7 files changed, 27 insertions(+), 101 deletions(-) diff --git a/erts/emulator/beam/emu/bs_instrs.tab b/erts/emulator/beam/emu/bs_instrs.tab index 1150b1172781..bb55deac13f1 100644 --- a/erts/emulator/beam/emu/bs_instrs.tab +++ b/erts/emulator/beam/emu/bs_instrs.tab @@ -280,17 +280,6 @@ i_bs_skip_bits2.execute(Fail, Unit) { } } -i_bs_skip_bits_imm2(Fail, Ms, Bits) { - ErlSubBits *sb = (ErlSubBits*)bitstring_val($Ms); - size_t new_offset; - new_offset = sb->start + ($Bits); - if (new_offset <= sb->end) { - sb->start = new_offset; - } else { - $FAIL($Fail); - } -} - bs_init_writable() { HEAVY_SWAPOUT; x(0) = erts_bs_init_writable(c_p, x(0)); diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab index 50dec2828f6b..8cbaba047d53 100644 --- a/erts/emulator/beam/emu/ops.tab +++ b/erts/emulator/beam/emu/ops.tab @@ -1189,10 +1189,16 @@ i_bs_get_float2 xy f? t s t d # Miscellaneous -bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u => - skip_bits2(Fail, Ms, Sz, Unit, Flags) +bs_skip_bits2 Fail=f Ms=xy Sz=xy Unit=u Flags=u => + i_bs_skip_bits2 Ms Sz Fail Unit + +# Starting with Erlang/OTP 26, bs_skip_bits2 with an immediate size is +# almost never found in optimized code. Therefore, there is no need to +# to implement it efficiently. + +bs_skip_bits2 Fail=f Ms=xy Sz Unit=u Flags=u => + move Sz x | bs_skip_bits2 Fail Ms x Unit Flags -i_bs_skip_bits_imm2 f? xy W i_bs_skip_bits2 xy xy f? t bs_test_tail2 Fail=f Ms=xy o => jump Fail diff --git a/erts/emulator/beam/generators.tab b/erts/emulator/beam/generators.tab index e48393f2d7e3..00328f47519f 100644 --- a/erts/emulator/beam/generators.tab +++ b/erts/emulator/beam/generators.tab @@ -81,72 +81,6 @@ gen.get_utf16(Fail, Ms, Flags, Dst) { return op; } -// Generate the fastest instruction for bs_skip_bits. -gen.skip_bits2(Fail, Ms, Size, Unit, Flags) { - BeamOp* op; - $NewBeamOp(S, op); - - $NativeEndian(Flags); - if (Size.type == TAG_a && Size.val == am_all) { - /* - * This kind of skip instruction will only be found in modules - * compiled before OTP 19. From OTP 19, the compiler generates - * a test_unit instruction of a bs_skip at the end of a - * binary. - * - * It is safe to replace the skip instruction with a test_unit - * instruction, because the position will never be used again. - * If the match context itself is used again, it will be used by - * a bs_restore2 instruction which will overwrite the position - * by one of the stored positions. - */ - $BeamOpNameArity(op, bs_test_unit, 3); - op->a[0] = Fail; - op->a[1] = Ms; - op->a[2] = Unit; - } else if (Size.type == TAG_i) { - $BeamOpNameArity(op, i_bs_skip_bits_imm2, 3); - op->a[0] = Fail; - op->a[1] = Ms; - op->a[2].type = TAG_u; - if (!beam_load_safe_mul(Size.val, Unit.val, &op->a[2].val)) { - goto error; - } - } else if (Size.type == TAG_q) { - Eterm big = beamfile_get_literal(&S->beam, Size.val); - Uint bigval; - - if (!term_to_Uint(big, &bigval)) { - error: - $BeamOpNameArity(op, jump, 1); - op->a[0] = Fail; - } else { - $BeamOpNameArity(op, i_bs_skip_bits_imm2, 3); - op->a[0] = Fail; - op->a[1] = Ms; - op->a[2].type = TAG_u; - if (!beam_load_safe_mul(bigval, Unit.val, &op->a[2].val)) { - goto error; - } - } - } else if (Size.type == TAG_x || Size.type == TAG_y) { - $BeamOpNameArity(op, i_bs_skip_bits2, 4); - op->a[0] = Ms; - op->a[1] = Size; - op->a[2] = Fail; - op->a[3] = Unit; - } else { - /* - * Invalid literal size. Can only happen if compiler - * optimizations are selectively disabled. For example, - * at the time of writing, [no_copt, no_type_opt] will allow - * skip instructions with invalid sizes to slip through. - */ - goto error; - } - return op; -} - // Creates an instruction that moves a literal lambda to a register. MakeLiteralFun(Op, Index, Arity, Dst) { SWord literal; diff --git a/erts/emulator/beam/jit/arm/instr_bs.cpp b/erts/emulator/beam/jit/arm/instr_bs.cpp index f6a84591c998..f6c8c917fd5c 100644 --- a/erts/emulator/beam/jit/arm/instr_bs.cpp +++ b/erts/emulator/beam/jit/arm/instr_bs.cpp @@ -510,13 +510,6 @@ void BeamModuleAssembler::emit_i_bs_skip_bits2(const ArgRegister &Ctx, } } -void BeamModuleAssembler::emit_i_bs_skip_bits_imm2(const ArgLabel &Fail, - const ArgRegister &Ctx, - const ArgWord &Bits) { - mov_arg(ARG1, Bits); - emit_bs_skip_bits(Fail, Ctx); -} - void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx, const ArgLabel &Fail, const ArgWord &Live, diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab index 7212e19e056a..d72d7ca3b54e 100644 --- a/erts/emulator/beam/jit/arm/ops.tab +++ b/erts/emulator/beam/jit/arm/ops.tab @@ -989,10 +989,16 @@ i_bs_get_float2 S f t s t d # Miscellaneous -bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u => - skip_bits2(Fail, Ms, Sz, Unit, Flags) +bs_skip_bits2 Fail=f Ms=xy Sz=xy Unit=u Flags=u => + i_bs_skip_bits2 Ms Sz Fail Unit + +# Starting with Erlang/OTP 26, bs_skip_bits2 with an immediate size is +# almost never found in optimized code. Therefore, there is no need to +# to implement it efficiently. + +bs_skip_bits2 Fail=f Ms=xy Sz Unit=u Flags=u => + move Sz x | bs_skip_bits2 Fail Ms x Unit Flags -i_bs_skip_bits_imm2 f S W i_bs_skip_bits2 S S f t bs_test_tail2 Fail=f Ms=xy o => jump Fail diff --git a/erts/emulator/beam/jit/x86/instr_bs.cpp b/erts/emulator/beam/jit/x86/instr_bs.cpp index d3c9e1c050d6..ea1b4d22c07c 100644 --- a/erts/emulator/beam/jit/x86/instr_bs.cpp +++ b/erts/emulator/beam/jit/x86/instr_bs.cpp @@ -481,14 +481,6 @@ void BeamModuleAssembler::emit_i_bs_skip_bits2(const ArgRegister &Ctx, } } -void BeamModuleAssembler::emit_i_bs_skip_bits_imm2(const ArgLabel &Fail, - const ArgRegister &Ctx, - const ArgWord &Bits) { - mov_arg(RET, Bits); - - emit_bs_skip_bits(Fail, Ctx); -} - void BeamModuleAssembler::emit_i_bs_get_binary2(const ArgRegister &Ctx, const ArgLabel &Fail, const ArgWord &Live, diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab index c66d824e3baf..a00899f36562 100644 --- a/erts/emulator/beam/jit/x86/ops.tab +++ b/erts/emulator/beam/jit/x86/ops.tab @@ -911,10 +911,16 @@ i_bs_get_float2 S f t s t d # Miscellaneous -bs_skip_bits2 Fail=f Ms=xy Sz=sq Unit=u Flags=u => - skip_bits2(Fail, Ms, Sz, Unit, Flags) +bs_skip_bits2 Fail=f Ms=xy Sz=xy Unit=u Flags=u => + i_bs_skip_bits2 Ms Sz Fail Unit + +# Starting with Erlang/OTP 26, bs_skip_bits2 with an immediate size is +# almost never found in optimized code. Therefore, there is no need to +# to implement it efficiently. + +bs_skip_bits2 Fail=f Ms=xy Sz Unit=u Flags=u => + move Sz x | bs_skip_bits2 Fail Ms x Unit Flags -i_bs_skip_bits_imm2 f S W i_bs_skip_bits2 S S f t bs_test_tail2 Fail=f Ms=xy o => jump Fail