Skip to content

Commit

Permalink
Merge pull request erlang#7553 from bjorng/bjorn/jit/integer-arithmetic
Browse files Browse the repository at this point in the history
Optimize integer arithmetic
  • Loading branch information
bjorng authored Aug 21, 2023
2 parents d3aa6c0 + 4ca352e commit 272e678
Show file tree
Hide file tree
Showing 16 changed files with 1,491 additions and 343 deletions.
378 changes: 256 additions & 122 deletions erts/emulator/beam/big.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions erts/emulator/beam/big.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Eterm small_times(Sint, Sint, Eterm*);
Eterm big_plus(Wterm, Wterm, Eterm*);
Eterm big_minus(Eterm, Eterm, Eterm*);
Eterm big_times(Eterm, Eterm, Eterm*);
Eterm big_mul_add(Eterm x, Eterm y, Eterm z, Eterm *r);

int big_div_rem(Eterm lhs, Eterm rhs,
Eterm *q_hp, Eterm *q,
Expand Down
92 changes: 92 additions & 0 deletions erts/emulator/beam/erl_arith.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,98 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)
}
}

Eterm
erts_mul_add(Process* p, Eterm arg1, Eterm arg2, Eterm arg3, Eterm* pp)
{
Eterm tmp_big1[2];
Eterm tmp_big2[2];
Eterm tmp_big3[2];
Eterm hdr;
Eterm res;
Eterm big_arg1, big_arg2, big_arg3;
dsize_t sz1, sz2, sz3, sz;
int need_heap;
Eterm* hp;
Eterm product;

big_arg1 = arg1;
big_arg2 = arg2;
big_arg3 = arg3;
switch (big_arg1 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
if (is_not_small(big_arg1)) {
break;
}
big_arg1 = small_to_big(signed_val(big_arg1), tmp_big1);
/* Fall through */
case TAG_PRIMARY_BOXED:
hdr = *boxed_val(big_arg1);
switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (big_arg2 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
if (is_not_small(big_arg2)) {
break;
}
big_arg2 = small_to_big(signed_val(big_arg2), tmp_big2);
/* Fall through */
case TAG_PRIMARY_BOXED:
hdr = *boxed_val(big_arg2);
switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (big_arg3 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
if (is_not_small(big_arg3)) {
break;
}
big_arg3 = small_to_big(signed_val(big_arg3), tmp_big3);
/* Fall through */
case TAG_PRIMARY_BOXED:
hdr = *boxed_val(big_arg3);
switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
sz1 = big_size(big_arg1);
sz2 = big_size(big_arg2);
sz3 = big_size(big_arg3);
sz = sz1 + sz2;
sz = MAX(sz, sz3) + 1;
need_heap = BIG_NEED_SIZE(sz);
#ifdef DEBUG
need_heap++;
#endif
hp = HeapFragOnlyAlloc(p, need_heap);

#ifdef DEBUG
hp[need_heap-1] = ERTS_HOLE_MARKER;
#endif
res = big_mul_add(big_arg1, big_arg2, big_arg3, hp);
ASSERT(hp[need_heap-1] == ERTS_HOLE_MARKER);
maybe_shrink(p, hp, res, need_heap);
if (is_nil(res)) {
p->freason = SYSTEM_LIMIT;
return THE_NON_VALUE;
}
return res;
}
}
}
}
}
}

/* At least one of the arguments is a float or invalid. */
product = erts_mixed_times(p, arg1, arg2);
*pp = product;
if (is_non_value(product)) {
return product;
} else {
return erts_mixed_plus(p, product, arg3);
}
}

Eterm
erts_mixed_div(Process* p, Eterm arg1, Eterm arg2)
{
Expand Down
1 change: 1 addition & 0 deletions erts/emulator/beam/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,7 @@ Eterm erts_unary_minus(Process* p, Eterm arg1);
Eterm erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2);
Eterm erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2);
Eterm erts_mixed_times(Process* p, Eterm arg1, Eterm arg2);
Eterm erts_mul_add(Process* p, Eterm arg1, Eterm arg2, Eterm arg3, Eterm* pp);
Eterm erts_mixed_div(Process* p, Eterm arg1, Eterm arg2);

int erts_int_div_rem(Process* p, Eterm arg1, Eterm arg2, Eterm *q, Eterm *r);
Expand Down
9 changes: 9 additions & 0 deletions erts/emulator/beam/jit/arm/beam_asm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,15 @@ class BeamModuleAssembler : public BeamAssembler,
const a64::Gp rhs_reg,
const Label next);

void emit_div_rem_literal(Sint divisor,
const ArgSource &Dividend,
arm::Gp dividend,
arm::Gp quotient,
arm::Gp remainder,
const Label &generic,
bool need_div,
bool need_rem);

void emit_div_rem(const ArgLabel &Fail,
const ArgSource &LHS,
const ArgSource &RHS,
Expand Down
7 changes: 5 additions & 2 deletions erts/emulator/beam/jit/arm/beam_asm_global.hpp.pl
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,16 @@
i_loop_rec_shared
i_test_yield_shared
i_bxor_body_shared
int128_to_big_shared
int_div_rem_body_shared
int_div_rem_guard_shared
is_in_range_shared
is_ge_lt_shared
minus_body_shared
mul_add_body_shared
mul_add_guard_shared
mul_body_shared
mul_guard_shared
new_map_shared
update_map_assoc_shared
unloaded_fun
Expand All @@ -106,8 +111,6 @@
raise_exception
raise_exception_shared
store_unaligned
times_body_shared
times_guard_shared
unary_minus_body_shared
update_map_exact_guard_shared
update_map_exact_body_shared
Expand Down
Loading

0 comments on commit 272e678

Please sign in to comment.