Skip to content

Commit

Permalink
Optimize test for arithmetic equality
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorng committed Nov 25, 2023
1 parent e590e99 commit e1bb0ae
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
25 changes: 17 additions & 8 deletions erts/emulator/beam/jit/arm/beam_asm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,14 +674,6 @@ struct BeamAssembler : public BeamAssemblerCommon {
}
}

/* Set the Z flag if Reg1 and Reg2 are both immediates. */
void emit_are_both_immediate(arm::Gp Reg1, arm::Gp Reg2) {
ERTS_CT_ASSERT(TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK);
a.and_(SUPER_TMP, Reg1, Reg2);
a.and_(SUPER_TMP, SUPER_TMP, imm(_TAG_PRIMARY_MASK));
a.cmp(SUPER_TMP, imm(TAG_PRIMARY_IMMED1));
}

/* Set the Z flag if Reg1 and Reg2 are definitely not equal based
* on their tags alone. (They may still be equal if both are
* immediates and all other bits are equal too.) */
Expand Down Expand Up @@ -1817,6 +1809,23 @@ class BeamModuleAssembler : public BeamAssembler,
}
}
}

/* Set the Z flag if Reg1 and Reg2 are both immediates. */
void emit_are_both_immediate(const ArgVal &Src1,
arm::Gp Reg1,
const ArgVal &Src2,
arm::Gp Reg2) {
ERTS_CT_ASSERT(TAG_PRIMARY_IMMED1 == _TAG_PRIMARY_MASK);
if (always_immediate(Src1)) {
a.and_(SUPER_TMP, Reg2, imm(_TAG_PRIMARY_MASK));
} else if (always_immediate(Src2)) {
a.and_(SUPER_TMP, Reg1, imm(_TAG_PRIMARY_MASK));
} else {
a.and_(SUPER_TMP, Reg1, Reg2);
a.and_(SUPER_TMP, SUPER_TMP, imm(_TAG_PRIMARY_MASK));
}
a.cmp(SUPER_TMP, imm(TAG_PRIMARY_IMMED1));
}
};

void beamasm_metadata_update(std::string module_name,
Expand Down
14 changes: 8 additions & 6 deletions erts/emulator/beam/jit/arm/instr_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,11 +1687,12 @@ void BeamModuleAssembler::emit_is_eq(const ArgLabel &Fail,
a.cmp(x.reg, y.reg);
a.b_eq(next);

if (X.isLiteral() || Y.isLiteral()) {
comment("skipped test for small because one operand is never small");
if (always_one_of<BeamTypeId::Cons, BeamTypeId::AlwaysBoxed>(X) ||
always_one_of<BeamTypeId::Cons, BeamTypeId::AlwaysBoxed>(X)) {
comment("skipped test for immediate because on operand never is");
} else {
/* We can skip deep comparisons when both args are immediates. */
emit_are_both_immediate(x.reg, y.reg);
emit_are_both_immediate(X, x.reg, Y, y.reg);
a.b_eq(resolve_beam_label(Fail, disp1MB));
}

Expand All @@ -1714,11 +1715,12 @@ void BeamModuleAssembler::emit_is_ne(const ArgLabel &Fail,
a.cmp(x.reg, y.reg);
a.b_eq(resolve_beam_label(Fail, disp1MB));

if (X.isLiteral() || Y.isLiteral()) {
comment("skipped test for small because one operand is never small");
if (always_one_of<BeamTypeId::Cons, BeamTypeId::AlwaysBoxed>(X) ||
always_one_of<BeamTypeId::Cons, BeamTypeId::AlwaysBoxed>(X)) {
comment("skipped test for immediate because on operand never is");
} else {
/* We can skip deep comparisons when both args are immediates. */
emit_are_both_immediate(x.reg, y.reg);
emit_are_both_immediate(X, x.reg, Y, y.reg);
a.b_eq(next);
}

Expand Down

0 comments on commit e1bb0ae

Please sign in to comment.