Skip to content

Commit

Permalink
[core] #ifdef PARROT_SLOW_MOD or fast % mod
Browse files Browse the repository at this point in the history
use optionally the 3.5% faster natural % for int mod,
which is "incorrect" or different with negative arguments.

mod is profiled as hot and slow (5.5%) in parrot-bench
with linux perf.
  • Loading branch information
Reini Urban committed Feb 1, 2015
1 parent 5aa3161 commit f0faeae
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 22 deletions.
8 changes: 8 additions & 0 deletions config/gen/config_h/feature_h.in
Expand Up @@ -255,6 +255,14 @@ print OUT <<'END_PRINT';
#define UNLIKELY(cond) EXPECT((cond),0)
END_PRINT

print OUT <<'END_PRINT';
/* No configure probe or cmdline option for this yet.
Optionally use fast '%' for mod, or the "corrected mod" for negative arguments.
See src/utils.c:Parrot_util_intval_mod()
This is ~3.5% slower. */
#define PARROT_SLOW_MOD
END_PRINT

print OUT <<'END_PRINT';

#endif /* PARROT_FEATURE_H_GUARD */
Expand Down
90 changes: 80 additions & 10 deletions src/ops/core_ops.c
Expand Up @@ -18145,25 +18145,53 @@ 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 defined(PARROT_SLOW_MOD)
IREG(1) = Parrot_util_intval_mod(IREG(1), IREG(2));

#else
IREG(1) = (IREG(1) % IREG(2));

#endif
;
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 defined(PARROT_SLOW_MOD)
IREG(1) = Parrot_util_intval_mod(IREG(1), ICONST(2));

#else
IREG(1) = (IREG(1) % ICONST(2));

#endif
;
return cur_opcode + 3;
}

opcode_t *
Parrot_mod_n_n(opcode_t *cur_opcode, PARROT_INTERP) {
NREG(1) = Parrot_util_floatval_mod(NREG(1), NREG(2));
#if defined(PARROT_SLOW_MOD)
NREG(1) = Parrot_util_floatval_mod(NREG(1), NREG(2));

#else
NREG(1) = ((NREG(1) - (NREG(2) * floor((NREG(1) / NREG(2))))));

#endif
;
return cur_opcode + 3;
}

opcode_t *
Parrot_mod_n_nc(opcode_t *cur_opcode, PARROT_INTERP) {
NREG(1) = Parrot_util_floatval_mod(NREG(1), NCONST(2));
#if defined(PARROT_SLOW_MOD)
NREG(1) = Parrot_util_floatval_mod(NREG(1), NCONST(2));

#else
NREG(1) = ((NREG(1) - (NCONST(2) * floor((NREG(1) / NCONST(2))))));

#endif
;
return cur_opcode + 3;
}

Expand Down Expand Up @@ -18199,37 +18227,79 @@ 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 defined(PARROT_SLOW_MOD)
IREG(1) = Parrot_util_intval_mod(IREG(2), IREG(3));

#else
IREG(1) = (IREG(2) % IREG(3));

#endif
;
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 defined(PARROT_SLOW_MOD)
IREG(1) = Parrot_util_intval_mod(ICONST(2), IREG(3));

#else
IREG(1) = (ICONST(2) % IREG(3));

#endif
;
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 defined(PARROT_SLOW_MOD)
IREG(1) = Parrot_util_intval_mod(IREG(2), ICONST(3));

#else
IREG(1) = (IREG(2) % ICONST(3));

#endif
;
return cur_opcode + 4;
}

opcode_t *
Parrot_mod_n_n_n(opcode_t *cur_opcode, PARROT_INTERP) {
NREG(1) = Parrot_util_floatval_mod(NREG(2), NREG(3));
#if defined(PARROT_SLOW_MOD)
NREG(1) = Parrot_util_floatval_mod(NREG(2), NREG(3));

#else
NREG(1) = ((NREG(2) - (NREG(3) * floor((NREG(2) / NREG(3))))));

#endif
;
return cur_opcode + 4;
}

opcode_t *
Parrot_mod_n_nc_n(opcode_t *cur_opcode, PARROT_INTERP) {
NREG(1) = Parrot_util_floatval_mod(NCONST(2), NREG(3));
#if defined(PARROT_SLOW_MOD)
NREG(1) = Parrot_util_floatval_mod(NCONST(2), NREG(3));

#else
NREG(1) = ((NCONST(2) - (NREG(3) * floor((NCONST(2) / NREG(3))))));

#endif
;
return cur_opcode + 4;
}

opcode_t *
Parrot_mod_n_n_nc(opcode_t *cur_opcode, PARROT_INTERP) {
NREG(1) = Parrot_util_floatval_mod(NREG(2), NCONST(3));
#if defined(PARROT_SLOW_MOD)
NREG(1) = Parrot_util_floatval_mod(NREG(2), NCONST(3));

#else
NREG(1) = ((NREG(2) - (NCONST(3) * floor((NREG(2) / NCONST(3))))));

#endif
;
return cur_opcode + 4;
}

Expand Down
22 changes: 19 additions & 3 deletions src/ops/math.ops
Expand Up @@ -564,11 +564,19 @@ References:
=cut

op mod(inout INT, in INT) {
$1 = Parrot_util_intval_mod($1, $2);
#ifdef PARROT_SLOW_MOD
$1 = Parrot_util_intval_mod($1, $2);
#else
$1 = $1 % $2;
#endif
}

op mod(inout NUM, in NUM) {
#ifdef PARROT_SLOW_MOD
$1 = Parrot_util_floatval_mod($1, $2);
#else
$1 = ($1 - $2 * floor($1 / $2));
#endif
}

inline op mod(invar PMC, invar PMC) {
Expand All @@ -584,11 +592,19 @@ inline op mod(invar PMC, in NUM) {
}

op mod(out INT, in INT, in INT) {
$1 = Parrot_util_intval_mod($2, $3);
#ifdef PARROT_SLOW_MOD
$1 = Parrot_util_intval_mod($2, $3);
#else
$1 = $2 % $3;
#endif
}

op mod(out NUM, in NUM, in NUM) {
#ifdef PARROT_SLOW_MOD
$1 = Parrot_util_floatval_mod($2, $3);
#else
$1 = ($2 - $3 * floor($2 / $3));
#endif
}

inline op mod(invar PMC, invar PMC, invar PMC) {
Expand Down Expand Up @@ -813,7 +829,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
45 changes: 36 additions & 9 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 @@ -945,25 +945,39 @@ Calculates modulus in place.

MULTI PMC *modulus(DEFAULT value, PMC *dest) :no_wb {
UNUSED(dest)
const INTVAL d = VTABLE_get_integer(INTERP, value);
const volatile INTVAL d = VTABLE_get_integer(INTERP, value);
volatile INTVAL result;
const volatile INTVAL i1 = SELF.get_integer();

if (d == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

#ifdef PARROT_SLOW_MOD
result = Parrot_util_intval_mod(i1, d);
#else
result = i1 % d;
#endif
return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
Parrot_util_intval_mod(SELF.get_integer(), d));
result);
}


VTABLE PMC *modulus_int(INTVAL value, PMC *dest) :no_wb {
UNUSED(dest)
volatile INTVAL result;
const volatile INTVAL i1 = SELF.get_integer();

if (value == 0)
Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_DIV_BY_ZERO,
"int modulus by zero");

#ifdef PARROT_SLOW_MOD
result = Parrot_util_intval_mod(i1, value);
#else
result = i1 % value;
#endif
return Parrot_pmc_new_init_int(INTERP, VTABLE_type(INTERP, SELF),
Parrot_util_intval_mod(SELF.get_integer(), value));
result);
}


Expand Down Expand Up @@ -993,23 +1007,36 @@ Calculates modulus in place.

MULTI void i_modulus(DEFAULT value) :manual_wb {
const INTVAL d = VTABLE_get_integer(INTERP, value);
const volatile INTVAL i1 = SELF.get_integer();
volatile INTVAL result;

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));
#ifdef PARROT_SLOW_MOD
result = Parrot_util_intval_mod(i1, d);
#else
result = i1 % d;
#endif
VTABLE_set_integer_native(INTERP, SELF, result);
}


VTABLE void i_modulus_int(INTVAL value) :manual_wb {
const volatile INTVAL i1 = SELF.get_integer();
volatile INTVAL result;

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));
#ifdef PARROT_SLOW_MOD
result = Parrot_util_intval_mod(i1, value);
#else
result = i1 % value;
#endif
VTABLE_set_integer_native(INTERP, SELF, result);
}


Expand Down

0 comments on commit f0faeae

Please sign in to comment.