Skip to content

Commit

Permalink
optimize integer mod
Browse files Browse the repository at this point in the history
for all positive int args use the HW mod insn,
and do not call Parrot_util_intval_mod().
This was profiled to be a bottleneck. 4% perf. win in parrot-bench.
  • Loading branch information
Reini Urban committed Jun 15, 2015
1 parent 63348c0 commit 24e1724
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 29 deletions.
1 change: 1 addition & 0 deletions ChangeLog
@@ -1,5 +1,6 @@
2014-06-16 release 7.5.0
- Core
+ Optimize mod_i_* ops and Integer pmc to avoid util_intval_mod
+ Coverity bugs fixed:
= missing_comma in optimizer.c
= nesting_indent_mismatch in runcore/subprof.c
Expand Down
70 changes: 65 additions & 5 deletions src/ops/core_ops.c
Expand Up @@ -18145,13 +18145,37 @@ Parrot_inc_p(opcode_t *cur_opcode, PARROT_INTERP) {

opcode_t *
Parrot_mod_i_i(opcode_t *cur_opcode, PARROT_INTERP) {
IREG(1) = Parrot_util_intval_mod(IREG(1), IREG(2));
if (IREG(2) == 0) {
IREG(1) = IREG(1);
}
else {
if ((IREG(1) > 0) && (IREG(2) > 0)) {
IREG(1) = (IREG(1) % IREG(2));
}
else {
IREG(1) = Parrot_util_intval_mod(IREG(1), IREG(2));
}

}

return cur_opcode + 3;
}

opcode_t *
Parrot_mod_i_ic(opcode_t *cur_opcode, PARROT_INTERP) {
IREG(1) = Parrot_util_intval_mod(IREG(1), ICONST(2));
if (ICONST(2) == 0) {
IREG(1) = IREG(1);
}
else {
if ((IREG(1) > 0) && (ICONST(2) > 0)) {
IREG(1) = (IREG(1) % ICONST(2));
}
else {
IREG(1) = Parrot_util_intval_mod(IREG(1), ICONST(2));
}

}

return cur_opcode + 3;
}

Expand Down Expand Up @@ -18199,19 +18223,55 @@ Parrot_mod_p_nc(opcode_t *cur_opcode, PARROT_INTERP) {

opcode_t *
Parrot_mod_i_i_i(opcode_t *cur_opcode, PARROT_INTERP) {
IREG(1) = Parrot_util_intval_mod(IREG(2), IREG(3));
if (IREG(3) == 0) {
IREG(1) = IREG(2);
}
else {
if ((IREG(2) > 0) && (IREG(3) > 0)) {
IREG(1) = (IREG(2) % IREG(3));
}
else {
IREG(1) = Parrot_util_intval_mod(IREG(2), IREG(3));
}

}

return cur_opcode + 4;
}

opcode_t *
Parrot_mod_i_ic_i(opcode_t *cur_opcode, PARROT_INTERP) {
IREG(1) = Parrot_util_intval_mod(ICONST(2), IREG(3));
if (IREG(3) == 0) {
IREG(1) = ICONST(2);
}
else {
if ((ICONST(2) > 0) && (IREG(3) > 0)) {
IREG(1) = (ICONST(2) % IREG(3));
}
else {
IREG(1) = Parrot_util_intval_mod(ICONST(2), IREG(3));
}

}

return cur_opcode + 4;
}

opcode_t *
Parrot_mod_i_i_ic(opcode_t *cur_opcode, PARROT_INTERP) {
IREG(1) = Parrot_util_intval_mod(IREG(2), ICONST(3));
if (ICONST(3) == 0) {
IREG(1) = IREG(2);
}
else {
if ((IREG(2) > 0) && (ICONST(3) > 0)) {
IREG(1) = (IREG(2) % ICONST(3));
}
else {
IREG(1) = Parrot_util_intval_mod(IREG(2), ICONST(3));
}

}

return cur_opcode + 4;
}

Expand Down
16 changes: 13 additions & 3 deletions src/ops/math.ops
Expand Up @@ -564,7 +564,12 @@ References:
=cut

op mod(inout INT, in INT) {
$1 = Parrot_util_intval_mod($1, $2);
if ($2 == 0)
$1 = $1;
else if ($1 > 0 && $2 > 0)
$1 = $1 % $2;
else
$1 = Parrot_util_intval_mod($1, $2);
}

op mod(inout NUM, in NUM) {
Expand All @@ -584,7 +589,12 @@ inline op mod(invar PMC, in NUM) {
}

op mod(out INT, in INT, in INT) {
$1 = Parrot_util_intval_mod($2, $3);
if ($3 == 0)
$1 = $2;
else if ($2 > 0 && $3 > 0)
$1 = $2 % $3;
else
$1 = Parrot_util_intval_mod($2, $3);
}

op mod(out NUM, in NUM, in NUM) {
Expand Down Expand Up @@ -813,7 +823,7 @@ inline op is_inf_or_nan(out INT, in NUM) {

=head1 COPYRIGHT

Copyright (C) 2001-2014, Parrot Foundation.
Copyright (C) 2001-2015, Parrot Foundation.

=head1 LICENSE

Expand Down
55 changes: 37 additions & 18 deletions src/pmc/integer.pmc
@@ -1,5 +1,5 @@
/*
Copyright (C) 2003-2014, Parrot Foundation.
Copyright (C) 2003-2015, Parrot Foundation.

=head1 NAME

Expand Down Expand Up @@ -950,9 +950,12 @@ Calculates modulus in place.
if (d == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
Parrot_util_intval_mod(SELF.get_integer(), d));
{
const INTVAL m = SELF.get_integer();
return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
(m > 0 && d > 0) ? m % d
: Parrot_util_intval_mod(m, d));
}
}


Expand All @@ -961,9 +964,12 @@ Calculates modulus in place.
if (value == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
Parrot_util_intval_mod(SELF.get_integer(), value));
{
const INTVAL m = SELF.get_integer();
return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
(m > 0 && value > 0) ? m % value
: Parrot_util_intval_mod(m, value));
}
}


Expand All @@ -978,9 +984,12 @@ Calculates modulus in place.
VTABLE_set_number_native(INTERP, result, value);
return result;
}
else
else {
const INTVAL m = SELF.get_integer();
return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
Parrot_util_intval_mod(SELF.get_integer(), (INTVAL)value));
(m > 0 && value > 0) ? m % (INTVAL)value
: Parrot_util_intval_mod(m, (INTVAL)value));
}
}


Expand All @@ -997,19 +1006,25 @@ Calculates modulus in place.
if (d == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

VTABLE_set_integer_native(INTERP, SELF,
Parrot_util_intval_mod(SELF.get_integer(), d));
{
const INTVAL m = SELF.get_integer();
VTABLE_set_integer_native(INTERP, SELF,
(m > 0 && d > 0) ? m % d
: Parrot_util_intval_mod(m, d));
}
}


VTABLE void i_modulus_int(INTVAL value) :manual_wb {
if (value == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

VTABLE_set_integer_native(INTERP, SELF,
Parrot_util_intval_mod(SELF.get_integer(), value));
{
const INTVAL m = SELF.get_integer();
VTABLE_set_integer_native(INTERP, SELF,
(m > 0 && value > 0) ? m % value
: Parrot_util_intval_mod(m, value));
}
}


Expand All @@ -1018,11 +1033,15 @@ Calculates modulus in place.
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

if (PARROT_FLOATVAL_IS_INF_OR_NAN(value))
if (PARROT_FLOATVAL_IS_INF_OR_NAN(value)) {
VTABLE_set_number_native(INTERP, SELF, value);
else
}
else {
const INTVAL m = SELF.get_integer();
VTABLE_set_integer_native(INTERP, SELF,
Parrot_util_intval_mod(SELF.get_integer(), (INTVAL)value));
(m > 0 && value > 0) ? m % (INTVAL)value
: Parrot_util_intval_mod(m, (INTVAL)value));
}
}

/*
Expand Down
6 changes: 3 additions & 3 deletions src/utils.c
@@ -1,5 +1,5 @@
/*
Copyright (C) 2001-2014, Parrot Foundation.
Copyright (C) 2001-2015, Parrot Foundation.
=head1 NAME
Expand Down Expand Up @@ -112,11 +112,11 @@ INTVAL
Parrot_util_intval_mod(INTVAL i2, INTVAL i3)
{
ASSERT_ARGS(Parrot_util_intval_mod)
INTVAL z = i3;

if (z == 0)
if (i3 == 0)
return i2;
else {
INTVAL z = i3;
INTVAL r;
INTVAL y;
int s = 0;
Expand Down

0 comments on commit 24e1724

Please sign in to comment.