Skip to content

Commit

Permalink
Generalize optimization of comparison to emtpy bitstring
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorng committed Nov 26, 2023
1 parent 25d1268 commit 66997a2
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions erts/emulator/beam/jit/arm/instr_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1555,15 +1555,40 @@ void BeamModuleAssembler::emit_is_eq_exact(const ArgLabel &Fail,
const ArgSource &Y) {
auto x = load_source(X, ARG1);

if (exact_type<BeamTypeId::Bitstring>(X) && Y.isLiteral()) {
if (Y.isLiteral()) {
Eterm literal = beamfile_get_literal(beam, Y.as<ArgLiteral>().get());

if (is_bitstring(literal) && bitstring_size(literal) == 0) {
comment("simplified equality test with empty binary");
arm::Gp boxed_ptr;

arm::Gp boxed_ptr = emit_ptr_val(ARG1, x.reg);
a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
a.cbnz(TMP1, resolve_beam_label(Fail, disp1MB));
comment("simplified equality test with empty binary");
emit_is_boxed(resolve_beam_label(Fail, dispUnknown), X, x.reg);
boxed_ptr = emit_ptr_val(ARG1, x.reg);
if (masked_types<BeamTypeId::MaybeBoxed>(X) ==
BeamTypeId::Bitstring) {
comment("eliminated check for known bitstring");
a.ldur(TMP1, emit_boxed_val(boxed_ptr, sizeof(Eterm)));
a.cbnz(TMP1, resolve_beam_label(Fail, disp1MB));
} else {
a.sub(TMP1, boxed_ptr, imm(TAG_PRIMARY_BOXED));
a.ldp(TMP1, TMP2, arm::Mem(TMP1));
/* The header mask with the binary sub tag bits
* removed (0b110011) is not possible to use as an
* immediate operand for 'and'. (See the note at the
* beginning of the file.) Therefore, use a simpler
* mask (0b110000) that will also clear the primary
* tag bits. That works because we KNOW that a boxed
* pointer always points to a header word and that the
* primary tag for a header is 0. */
const auto mask = _BITSTRING_TAG_MASK & ~_TAG_PRIMARY_MASK;
ERTS_CT_ASSERT(TAG_PRIMARY_HEADER == 0);
ERTS_CT_ASSERT(_TAG_HEADER_HEAP_BITS ==
(_TAG_HEADER_HEAP_BITS & mask));
a.and_(TMP1, TMP1, imm(mask));
a.cmp(TMP1, imm(_TAG_HEADER_HEAP_BITS));
a.ccmp(TMP2, imm(0), imm(NZCV::kNone), imm(arm::CondCode::kEQ));
a.b_ne(resolve_beam_label(Fail, disp1MB));
}
return;
}
}
Expand Down

0 comments on commit 66997a2

Please sign in to comment.