Skip to content

Commit

Permalink
Cache registers in more instructions
Browse files Browse the repository at this point in the history
It turns out to be useful to preserve the register cache in the
`bs_get_position` and `bs_set_position` instructions.
  • Loading branch information
bjorng committed Nov 4, 2024
1 parent ca6bc56 commit 8d92b40
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 17 deletions.
31 changes: 21 additions & 10 deletions erts/emulator/beam/jit/arm/instr_bs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,22 @@ void BeamModuleAssembler::emit_i_bs_match_string(const ArgRegister &Ctx,
void BeamModuleAssembler::emit_i_bs_get_position(const ArgRegister &Ctx,
const ArgRegister &Dst) {
const int start_offset = offsetof(ErlSubBits, start);
auto ctx_reg = load_source(Ctx);
auto dst_reg = init_destination(Dst, TMP2);
auto ctx = load_source(Ctx);
auto dst = init_destination(Dst, TMP2);
a64::Gp ctx_reg = ctx.reg;
a64::Gp dst_reg = dst.reg;

/* Match contexts can never be literals, so we can skip clearing literal
* tags. */
a.ldur(dst_reg.reg, emit_boxed_val(ctx_reg.reg, start_offset));
a.lsl(dst_reg.reg, dst_reg.reg, imm(_TAG_IMMED1_SIZE));
a.orr(dst_reg.reg, dst_reg.reg, imm(_TAG_IMMED1_SMALL));
preserve_cache(
[&]() {
a.ldur(dst_reg, emit_boxed_val(ctx_reg, start_offset));
a.lsl(dst_reg, dst_reg, imm(_TAG_IMMED1_SIZE));
a.orr(dst_reg, dst_reg, imm(_TAG_IMMED1_SMALL));
},
dst_reg);

flush_var(dst_reg);
flush_var(dst);
}

void BeamModuleAssembler::emit_bs_get_small(const Label &fail,
Expand Down Expand Up @@ -368,9 +374,15 @@ void BeamModuleAssembler::emit_bs_set_position(const ArgRegister &Ctx,
const ArgRegister &Pos) {
const int start_offset = offsetof(ErlSubBits, start);
auto [ctx, pos] = load_sources(Ctx, TMP1, Pos, TMP2);

a.lsr(TMP2, pos.reg, imm(_TAG_IMMED1_SIZE));
a.stur(TMP2, emit_boxed_val(ctx.reg, start_offset));
a64::Gp ctx_reg = ctx.reg;
a64::Gp pos_reg = pos.reg;

preserve_cache(
[&]() {
a.lsr(TMP2, pos_reg, imm(_TAG_IMMED1_SIZE));
a.stur(TMP2, emit_boxed_val(ctx_reg, start_offset));
},
TMP2);
}

void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx,
Expand Down Expand Up @@ -558,7 +570,6 @@ void BeamModuleAssembler::emit_i_bs_get_bin_and_tail(const ArgRegister &Ctx,
mov_arg(Dst2, ARG1);
}


void BeamModuleAssembler::emit_i_bs_get_float2(const ArgRegister &Ctx,
const ArgLabel &Fail,
const ArgWord &Live,
Expand Down
25 changes: 18 additions & 7 deletions erts/emulator/beam/jit/x86/instr_bs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,22 @@ void BeamModuleAssembler::emit_i_bs_match_string(const ArgRegister &Ctx,

void BeamModuleAssembler::emit_i_bs_get_position(const ArgRegister &Ctx,
const ArgRegister &Dst) {
x86::Gp tmp_reg = alloc_temp_reg();

mov_arg(ARG1, Ctx);

/* Match contexts can never be literals, so we can skip clearing literal
* tags. */
a.mov(ARG1, emit_boxed_val(ARG1, offsetof(ErlSubBits, start)));
a.sal(ARG1, imm(_TAG_IMMED1_SIZE));
a.or_(ARG1, imm(_TAG_IMMED1_SMALL));

mov_arg(Dst, ARG1);
mov_preserve_cache(tmp_reg,
emit_boxed_val(ARG1, offsetof(ErlSubBits, start)));
preserve_cache(
[&]() {
a.sal(tmp_reg, imm(_TAG_IMMED1_SIZE));
a.or_(tmp_reg, imm(_TAG_IMMED1_SMALL));
},
tmp_reg);

mov_arg(Dst, tmp_reg);
}

void BeamModuleAssembler::emit_bs_get_small(const Label &fail,
Expand Down Expand Up @@ -385,8 +392,12 @@ void BeamModuleAssembler::emit_bs_set_position(const ArgRegister &Ctx,
mov_arg(ARG1, Ctx);
mov_arg(ARG2, Pos);

a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
a.mov(emit_boxed_val(ARG1, offsetof(ErlSubBits, start)), ARG2);
preserve_cache(
[&]() {
a.sar(ARG2, imm(_TAG_IMMED1_SIZE));
},
ARG2);
mov_preserve_cache(emit_boxed_val(ARG1, offsetof(ErlSubBits, start)), ARG2);
}

void BeamModuleAssembler::emit_i_bs_get_binary_all2(const ArgRegister &Ctx,
Expand Down

0 comments on commit 8d92b40

Please sign in to comment.