Skip to content

Commit

Permalink
Optimized randomx_reciprocal
Browse files Browse the repository at this point in the history
Also limited it to 32 bit because it's supposed to work only with 32-bit values, according to the specs.
  • Loading branch information
SChernykh committed Oct 20, 2023
1 parent 5fc512e commit d970a67
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 38 deletions.
19 changes: 4 additions & 15 deletions src/jit_compiler_a64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ void JitCompilerA64::h_ISMULH_M(Instruction& instr, uint32_t& codePos)

void JitCompilerA64::h_IMUL_RCP(Instruction& instr, uint32_t& codePos)
{
const uint64_t divisor = instr.getImm32();
const uint32_t divisor = instr.getImm32();
if (isZeroOrPowerOf2(divisor))
return;

Expand All @@ -695,22 +695,11 @@ void JitCompilerA64::h_IMUL_RCP(Instruction& instr, uint32_t& codePos)
constexpr uint32_t tmp_reg = 20;
const uint32_t dst = IntRegMap[instr.dst];

constexpr uint64_t N = 1ULL << 63;
const uint64_t q = N / divisor;
const uint64_t r = N % divisor;
#ifdef __GNUC__
const uint64_t shift = 64 - __builtin_clzll(divisor);
#else
uint64_t shift = 32;
for (uint64_t k = 1U << 31; (k & divisor) == 0; k >>= 1)
--shift;
#endif

const uint32_t literal_id = (ImulRcpLiteralsEnd - literalPos) / sizeof(uint64_t);

literalPos -= sizeof(uint64_t);
const uint64_t randomx_reciprocal = (q << shift) + ((r << shift) / divisor);
memcpy(code + literalPos, &randomx_reciprocal, sizeof(randomx_reciprocal));

const uint64_t reciprocal = randomx_reciprocal_fast(divisor);
memcpy(code + literalPos, &reciprocal, sizeof(reciprocal));

if (literal_id < 12)
{
Expand Down
34 changes: 13 additions & 21 deletions src/reciprocal.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ret
*/
uint64_t randomx_reciprocal(uint64_t divisor) {
uint64_t randomx_reciprocal(uint32_t divisor) {

assert(divisor != 0);

const uint64_t p2exp63 = 1ULL << 63;
const uint64_t q = p2exp63 / divisor;
const uint64_t r = p2exp63 % divisor;

#ifdef __GNUC__
const uint32_t shift = 64 - __builtin_clzll(divisor);
#else
uint32_t shift = 32;
for (uint32_t k = 1U << 31; (k & divisor) == 0; k >>= 1)
--shift;
#endif

uint64_t quotient = p2exp63 / divisor, remainder = p2exp63 % divisor;

unsigned bsr = 0; //highest set bit in divisor

for (uint64_t bit = divisor; bit > 0; bit >>= 1)
bsr++;

for (unsigned shift = 0; shift < bsr; shift++) {
if (remainder >= divisor - remainder) {
quotient = quotient * 2 + 1;
remainder = remainder * 2 - divisor;
}
else {
quotient = quotient * 2;
remainder = remainder * 2;
}
}

return quotient;
return (q << shift) + ((r << shift) / divisor);
}

#if !RANDOMX_HAVE_FAST_RECIPROCAL

uint64_t randomx_reciprocal_fast(uint64_t divisor) {
uint64_t randomx_reciprocal_fast(uint32_t divisor) {
return randomx_reciprocal(divisor);
}

Expand Down
4 changes: 2 additions & 2 deletions src/reciprocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern "C" {
#endif

uint64_t randomx_reciprocal(uint64_t);
uint64_t randomx_reciprocal_fast(uint64_t);
uint64_t randomx_reciprocal(uint32_t);
uint64_t randomx_reciprocal_fast(uint32_t);

#if defined(__cplusplus)
}
Expand Down

0 comments on commit d970a67

Please sign in to comment.