diff --git a/doc/program.asm b/doc/program.asm index 6609d89..99d26f3 100644 --- a/doc/program.asm +++ b/doc/program.asm @@ -95,8 +95,8 @@ randomx_isn_23: mulpd xmm6, xmm8 randomx_isn_24: ; CBRANCH 149087159, COND 13 - add r8, 149087159 - test r8, 1040384 + add r10, 149087159 + test r10, 1040384 jz randomx_isn_21 randomx_isn_25: ; FADD_R f3, a0 @@ -197,8 +197,8 @@ randomx_isn_53: subpd xmm2, xmm8 randomx_isn_54: ; CBRANCH 1917049931, COND 12 - add r8, 1917049931 - test r8, 520192 + add r11, 1917049931 + test r11, 520192 jz randomx_isn_52 randomx_isn_55: ; IXOR_R r2, r3 @@ -329,8 +329,8 @@ randomx_isn_88: imul r9, r11 randomx_isn_89: ; CBRANCH -122257389, COND 13 - add r8, -122249197 - test r8, 1040384 + add r13, -122249197 + test r13, 1040384 jz randomx_isn_75 randomx_isn_90: ; ISTORE L1[r5+228116180], r7 diff --git a/src/assembly_generator_x86.cpp b/src/assembly_generator_x86.cpp index 259901c..be3e359 100644 --- a/src/assembly_generator_x86.cpp +++ b/src/assembly_generator_x86.cpp @@ -45,7 +45,8 @@ namespace randomx { void AssemblyGeneratorX86::generateProgram(Program& prog) { for (unsigned i = 0; i < RegistersCount; ++i) { - registerUsage[i] = -1; + registerUsage[i].lastUsed = -1; + registerUsage[i].count = 0; } asmCode.str(std::string()); //clear for (unsigned i = 0; i < prog.getSize(); ++i) { @@ -215,18 +216,6 @@ namespace randomx { asmCode << "}" << std::endl; } - int AssemblyGeneratorX86::getConditionRegister() { - int min = INT_MAX; - int minIndex; - for (unsigned i = 0; i < 8; ++i) { - if (registerUsage[i] < min) { - min = registerUsage[i]; - minIndex = i; - } - } - return minIndex; - } - void AssemblyGeneratorX86::traceint(Instruction& instr) { if (trace) { asmCode << "\tpush " << regR[instr.dst] << std::endl; @@ -273,7 +262,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if(instr.dst == RegisterNeedsDisplacement) asmCode << "\tlea " << regR[instr.dst] << ", [" << regR[instr.dst] << "+" << regR[instr.src] << "*" << (1 << (instr.getModShift())) << std::showpos << (int32_t)instr.getImm32() << std::noshowpos << "]" << std::endl; else @@ -282,7 +271,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); asmCode << "\tadd " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; @@ -294,7 +283,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_ISUB_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { asmCode << "\tsub " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; } @@ -305,7 +294,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_ISUB_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); asmCode << "\tsub " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; @@ -317,7 +306,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IMUL_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { asmCode << "\timul " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; } @@ -328,7 +317,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IMUL_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); asmCode << "\timul " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; @@ -341,7 +330,7 @@ namespace randomx { //4 uOPs void AssemblyGeneratorX86::h_IMULH_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; asmCode << "\tmul " << regR[instr.src] << std::endl; asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl; @@ -349,7 +338,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IMULH_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr, "ecx"); asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; @@ -364,7 +353,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_ISMULH_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; asmCode << "\timul " << regR[instr.src] << std::endl; asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl; @@ -372,7 +361,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_ISMULH_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr, "ecx"); asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; @@ -387,13 +376,13 @@ namespace randomx { } void AssemblyGeneratorX86::h_INEG_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; asmCode << "\tneg " << regR[instr.dst] << std::endl; traceint(instr); } void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { asmCode << "\txor " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; } @@ -404,7 +393,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IXOR_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); asmCode << "\txor " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; @@ -416,7 +405,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IROR_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; asmCode << "\tror " << regR[instr.dst] << ", cl" << std::endl; @@ -428,7 +417,7 @@ namespace randomx { } void AssemblyGeneratorX86::h_IROL_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; asmCode << "\trol " << regR[instr.dst] << ", cl" << std::endl; @@ -441,7 +430,7 @@ namespace randomx { void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) { if (instr.getImm32() != 0) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; asmCode << "\tmov rax, " << randomx_reciprocal(instr.getImm32()) << std::endl; asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl; traceint(instr); @@ -453,8 +442,8 @@ namespace randomx { void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) { if (instr.src != instr.dst) { - registerUsage[instr.dst] = i; - registerUsage[instr.src] = i; + registerUsage[instr.dst].lastUsed = i; + registerUsage[instr.src].lastUsed = i; asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; traceint(instr); } @@ -541,14 +530,16 @@ namespace randomx { } void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) { - int reg = getConditionRegister(); - int target = registerUsage[reg] + 1; + int reg = getConditionRegister(registerUsage); + int target = registerUsage[reg].lastUsed + 1; + registerUsage[reg].count++; int shift = instr.getModCond(); asmCode << "\tadd " << regR[reg] << ", " << (int32_t)(instr.getImm32() | (1 << shift)) << std::endl; asmCode << "\ttest " << regR[reg] << ", " << (ConditionMask << shift) << std::endl; asmCode << "\tjz randomx_isn_" << target << std::endl; - for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used - registerUsage[j] = i; + //mark all registers as used + for (unsigned j = 0; j < RegistersCount; ++j) { + registerUsage[j].lastUsed = i; } } diff --git a/src/assembly_generator_x86.hpp b/src/assembly_generator_x86.hpp index f0cc89a..a7c8556 100644 --- a/src/assembly_generator_x86.hpp +++ b/src/assembly_generator_x86.hpp @@ -43,7 +43,6 @@ namespace randomx { void genAddressReg(Instruction&, const char*); void genAddressRegDst(Instruction&, int); int32_t genAddressImm(Instruction&); - int getConditionRegister(); void generateCode(Instruction&, int); void traceint(Instruction&); void traceflt(Instruction&); @@ -82,6 +81,6 @@ namespace randomx { static InstructionGenerator engine[256]; std::stringstream asmCode; - int registerUsage[RegistersCount]; + RegisterUsage registerUsage[RegistersCount]; }; } \ No newline at end of file diff --git a/src/common.hpp b/src/common.hpp index 09811e5..671e24d 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -88,6 +88,11 @@ namespace randomx { double hi; }; + struct RegisterUsage { + int32_t lastUsed; + int32_t count; + }; + constexpr uint32_t ScratchpadL1 = RANDOMX_SCRATCHPAD_L1 / sizeof(int_reg_t); constexpr uint32_t ScratchpadL2 = RANDOMX_SCRATCHPAD_L2 / sizeof(int_reg_t); constexpr uint32_t ScratchpadL3 = RANDOMX_SCRATCHPAD_L3 / sizeof(int_reg_t); @@ -102,6 +107,21 @@ namespace randomx { constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register constexpr int RegisterNeedsSib = 4; //x86 r12 register + inline int getConditionRegister(RegisterUsage(®isterUsage)[RegistersCount]) { + int min = INT_MAX; + int minCount = 0; + int minIndex; + //prefer registers that have been used as a condition register fewer times + for (unsigned i = 0; i < RegistersCount; ++i) { + if (registerUsage[i].lastUsed < min || (registerUsage[i].lastUsed == min && registerUsage[i].count < minCount)) { + min = registerUsage[i].lastUsed; + minCount = registerUsage[i].count; + minIndex = i; + } + } + return minIndex; + } + struct MemoryRegisters { addr_t mx, ma; uint8_t* memory = nullptr; diff --git a/src/jit_compiler_x86.cpp b/src/jit_compiler_x86.cpp index 10b1059..cfda4f9 100644 --- a/src/jit_compiler_x86.cpp +++ b/src/jit_compiler_x86.cpp @@ -299,7 +299,8 @@ namespace randomx { void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) { instructionOffsets.clear(); for (unsigned i = 0; i < 8; ++i) { - registerUsage[i] = -1; + registerUsage[i].lastUsed = -1; + registerUsage[i].count = 0; } codePos = prologueSize; memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask)); @@ -468,7 +469,7 @@ namespace randomx { } void JitCompilerX86::h_IADD_RS(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; emit(REX_LEA); if (instr.dst == RegisterNeedsDisplacement) emitByte(0xac); @@ -480,7 +481,7 @@ namespace randomx { } void JitCompilerX86::h_IADD_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); emit(REX_ADD_RM); @@ -499,7 +500,7 @@ namespace randomx { } void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { emit(REX_SUB_RR); emitByte(0xc0 + 8 * instr.dst + instr.src); @@ -512,7 +513,7 @@ namespace randomx { } void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); emit(REX_SUB_RM); @@ -527,7 +528,7 @@ namespace randomx { } void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { emit(REX_IMUL_RR); emitByte(0xc0 + 8 * instr.dst + instr.src); @@ -540,7 +541,7 @@ namespace randomx { } void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); emit(REX_IMUL_RM); @@ -555,7 +556,7 @@ namespace randomx { } void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; emit(REX_MOV_RR64); emitByte(0xc0 + instr.dst); emit(REX_MUL_R); @@ -565,7 +566,7 @@ namespace randomx { } void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr, false); emit(REX_MOV_RR64); @@ -584,7 +585,7 @@ namespace randomx { } void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; emit(REX_MOV_RR64); emitByte(0xc0 + instr.dst); emit(REX_MUL_R); @@ -594,7 +595,7 @@ namespace randomx { } void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr, false); emit(REX_MOV_RR64); @@ -614,7 +615,7 @@ namespace randomx { void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) { if (instr.getImm32() != 0) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; emit(MOV_RAX_I); emit64(randomx_reciprocal(instr.getImm32())); emit(REX_IMUL_RM); @@ -623,13 +624,13 @@ namespace randomx { } void JitCompilerX86::h_INEG_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; emit(REX_NEG); emitByte(0xd8 + instr.dst); } void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { emit(REX_XOR_RR); emitByte(0xc0 + 8 * instr.dst + instr.src); @@ -642,7 +643,7 @@ namespace randomx { } void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { genAddressReg(instr); emit(REX_XOR_RM); @@ -657,7 +658,7 @@ namespace randomx { } void JitCompilerX86::h_IROR_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { emit(REX_MOV_RR); emitByte(0xc8 + instr.src); @@ -672,7 +673,7 @@ namespace randomx { } void JitCompilerX86::h_IROL_R(Instruction& instr, int i) { - registerUsage[instr.dst] = i; + registerUsage[instr.dst].lastUsed = i; if (instr.src != instr.dst) { emit(REX_MOV_RR); emitByte(0xc8 + instr.src); @@ -688,8 +689,8 @@ namespace randomx { void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) { if (instr.src != instr.dst) { - registerUsage[instr.dst] = i; - registerUsage[instr.src] = i; + registerUsage[instr.dst].lastUsed = i; + registerUsage[instr.src].lastUsed = i; emit(REX_XCHG); emitByte(0xc0 + instr.src + 8 * instr.dst); } @@ -770,21 +771,10 @@ namespace randomx { emit(AND_OR_MOV_LDMXCSR); } - int JitCompilerX86::getConditionRegister() { - int min = INT_MAX; - int minIndex; - for (unsigned i = 0; i < RegistersCount; ++i) { - if (registerUsage[i] < min) { - min = registerUsage[i]; - minIndex = i; - } - } - return minIndex; - } - void JitCompilerX86::h_CBRANCH(Instruction& instr, int i) { - int reg = getConditionRegister(); - int target = registerUsage[reg] + 1; + int reg = getConditionRegister(registerUsage); + int target = registerUsage[reg].lastUsed + 1; + registerUsage[reg].count++; int shift = instr.getModCond(); emit(REX_ADD_I); emitByte(0xc0 + reg); @@ -794,8 +784,9 @@ namespace randomx { emit32(ConditionMask << shift); emit(JZ); emit32(instructionOffsets[target] - (codePos + 4)); - for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used - registerUsage[j] = i; + //mark all registers as used + for (unsigned j = 0; j < RegistersCount; ++j) { + registerUsage[j].lastUsed = i; } } diff --git a/src/jit_compiler_x86.hpp b/src/jit_compiler_x86.hpp index 98f1cb4..5e64cb2 100644 --- a/src/jit_compiler_x86.hpp +++ b/src/jit_compiler_x86.hpp @@ -58,13 +58,12 @@ namespace randomx { private: static InstructionGeneratorX86 engine[256]; std::vector instructionOffsets; - int registerUsage[8]; + RegisterUsage registerUsage[RegistersCount]; uint8_t* code; int32_t codePos; void generateProgramPrologue(Program&, ProgramConfiguration&); void generateProgramEpilogue(Program&); - int getConditionRegister(); void genAddressReg(Instruction&, bool); void genAddressRegDst(Instruction&, bool); void genAddressImm(Instruction&); diff --git a/src/tests/benchmark.cpp b/src/tests/benchmark.cpp index cedd3b0..3fb2cc2 100644 --- a/src/tests/benchmark.cpp +++ b/src/tests/benchmark.cpp @@ -229,7 +229,7 @@ int main(int argc, char** argv) { std::cout << "Calculated result: "; result.print(std::cout); if (noncesCount == 1000 && seedValue == 0) - std::cout << "Reference result: 804fed4a3dc4ed12917a210aad295925544e688e28549d7178eb27f412476a10" << std::endl; + std::cout << "Reference result: df0862de0bedf2da0432a5eeb097453f2b020d00eadc60c32ae27b8d9d10ee0c" << std::endl; if (!miningMode) { std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl; } diff --git a/src/vm_interpreted.cpp b/src/vm_interpreted.cpp index fbb96ad..25e2a54 100644 --- a/src/vm_interpreted.cpp +++ b/src/vm_interpreted.cpp @@ -265,18 +265,6 @@ namespace randomx { _mm_store_pd(®.e[i].lo, e[i]); } - static int getConditionRegister(int(®isterUsage)[RegistersCount]) { - int min = INT_MAX; - int minIndex; - for (unsigned i = 0; i < RegistersCount; ++i) { - if (registerUsage[i] < min) { - min = registerUsage[i]; - minIndex = i; - } - } - return minIndex; - } - template void InterpretedVm::datasetRead(uint32_t address, int_reg_t(&r)[RegistersCount]) { uint64_t* datasetLine = (uint64_t*)(mem.memory + address); @@ -288,9 +276,10 @@ namespace randomx { template void InterpretedVm::precompileProgram(int_reg_t(&r)[RegistersCount], __m128d (&f)[RegisterCountFlt], __m128d (&e)[RegisterCountFlt], __m128d (&a)[RegisterCountFlt]) { - int registerUsage[RegistersCount]; + RegisterUsage registerUsage[RegistersCount]; for (unsigned i = 0; i < RegistersCount; ++i) { - registerUsage[i] = -1; + registerUsage[i].lastUsed = -1; + registerUsage[i].count = 0; } for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) { auto& instr = program(i); @@ -311,7 +300,7 @@ namespace randomx { ibc.shift = instr.getModShift(); ibc.imm = signExtend2sCompl(instr.getImm32()); } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IADD_M) { @@ -328,7 +317,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(ISUB_R) { @@ -343,7 +332,7 @@ namespace randomx { ibc.imm = signExtend2sCompl(instr.getImm32()); ibc.isrc = &ibc.imm; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(ISUB_M) { @@ -360,7 +349,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IMUL_R) { @@ -375,7 +364,7 @@ namespace randomx { ibc.imm = signExtend2sCompl(instr.getImm32()); ibc.isrc = &ibc.imm; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IMUL_M) { @@ -392,7 +381,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IMULH_R) { @@ -401,7 +390,7 @@ namespace randomx { ibc.type = InstructionType::IMULH_R; ibc.idst = &r[dst]; ibc.isrc = &r[src]; - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IMULH_M) { @@ -418,7 +407,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(ISMULH_R) { @@ -427,7 +416,7 @@ namespace randomx { ibc.type = InstructionType::ISMULH_R; ibc.idst = &r[dst]; ibc.isrc = &r[src]; - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(ISMULH_M) { @@ -444,7 +433,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IMUL_RCP) { @@ -455,7 +444,7 @@ namespace randomx { ibc.idst = &r[dst]; ibc.imm = randomx_reciprocal(divisor); ibc.isrc = &ibc.imm; - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } else { ibc.type = InstructionType::NOP; @@ -466,7 +455,7 @@ namespace randomx { auto dst = instr.dst % RegistersCount; ibc.type = InstructionType::INEG_R; ibc.idst = &r[dst]; - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IXOR_R) { @@ -481,7 +470,7 @@ namespace randomx { ibc.imm = signExtend2sCompl(instr.getImm32()); ibc.isrc = &ibc.imm; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IXOR_M) { @@ -498,7 +487,7 @@ namespace randomx { ibc.isrc = &Zero; ibc.memMask = ScratchpadL3Mask; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IROR_R) { @@ -513,7 +502,7 @@ namespace randomx { ibc.imm = instr.getImm32(); ibc.isrc = &ibc.imm; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(IROL_R) { @@ -528,7 +517,7 @@ namespace randomx { ibc.imm = instr.getImm32(); ibc.isrc = &ibc.imm; } - registerUsage[dst] = i; + registerUsage[dst].lastUsed = i; } break; CASE_REP(ISWAP_R) { @@ -538,8 +527,8 @@ namespace randomx { ibc.idst = &r[dst]; ibc.isrc = &r[src]; ibc.type = InstructionType::ISWAP_R; - registerUsage[dst] = i; - registerUsage[src] = i; + registerUsage[dst].lastUsed = i; + registerUsage[src].lastUsed = i; } else { ibc.type = InstructionType::NOP; @@ -626,13 +615,15 @@ namespace randomx { //jump condition int reg = getConditionRegister(registerUsage); ibc.isrc = &r[reg]; - ibc.target = registerUsage[reg]; + ibc.target = registerUsage[reg].lastUsed; + registerUsage[reg].count++; int shift = instr.getModCond(); const uint64_t conditionMask = ConditionMask << instr.getModCond(); ibc.imm = signExtend2sCompl(instr.getImm32()) | (1ULL << shift); ibc.memMask = ConditionMask << shift; - for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used - registerUsage[j] = i; + //mark all registers as used + for (unsigned j = 0; j < RegistersCount; ++j) { + registerUsage[j].lastUsed = i; } } break;