diff --git a/erts/emulator/beam/jit/arm/beam_asm.hpp b/erts/emulator/beam/jit/arm/beam_asm.hpp index a619d10833d3..9f01c8d1c826 100644 --- a/erts/emulator/beam/jit/arm/beam_asm.hpp +++ b/erts/emulator/beam/jit/arm/beam_asm.hpp @@ -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.) */ @@ -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, diff --git a/erts/emulator/beam/jit/arm/instr_common.cpp b/erts/emulator/beam/jit/arm/instr_common.cpp index 7af2cc353fe3..f08d1a35546b 100644 --- a/erts/emulator/beam/jit/arm/instr_common.cpp +++ b/erts/emulator/beam/jit/arm/instr_common.cpp @@ -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(X) || + always_one_of(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)); } @@ -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(X) || + always_one_of(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); }