Skip to content

Commit 3cf6a30

Browse files
committed
Fixed biased condition register selection
1 parent 5543fb5 commit 3cf6a30

8 files changed

+107
-116
lines changed

doc/program.asm

+6-6
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ randomx_isn_23:
9595
mulpd xmm6, xmm8
9696
randomx_isn_24:
9797
; CBRANCH 149087159, COND 13
98-
add r8, 149087159
99-
test r8, 1040384
98+
add r10, 149087159
99+
test r10, 1040384
100100
jz randomx_isn_21
101101
randomx_isn_25:
102102
; FADD_R f3, a0
@@ -197,8 +197,8 @@ randomx_isn_53:
197197
subpd xmm2, xmm8
198198
randomx_isn_54:
199199
; CBRANCH 1917049931, COND 12
200-
add r8, 1917049931
201-
test r8, 520192
200+
add r11, 1917049931
201+
test r11, 520192
202202
jz randomx_isn_52
203203
randomx_isn_55:
204204
; IXOR_R r2, r3
@@ -329,8 +329,8 @@ randomx_isn_88:
329329
imul r9, r11
330330
randomx_isn_89:
331331
; CBRANCH -122257389, COND 13
332-
add r8, -122249197
333-
test r8, 1040384
332+
add r13, -122249197
333+
test r13, 1040384
334334
jz randomx_isn_75
335335
randomx_isn_90:
336336
; ISTORE L1[r5+228116180], r7

src/assembly_generator_x86.cpp

+26-35
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ namespace randomx {
4545

4646
void AssemblyGeneratorX86::generateProgram(Program& prog) {
4747
for (unsigned i = 0; i < RegistersCount; ++i) {
48-
registerUsage[i] = -1;
48+
registerUsage[i].lastUsed = -1;
49+
registerUsage[i].count = 0;
4950
}
5051
asmCode.str(std::string()); //clear
5152
for (unsigned i = 0; i < prog.getSize(); ++i) {
@@ -215,18 +216,6 @@ namespace randomx {
215216
asmCode << "}" << std::endl;
216217
}
217218

218-
int AssemblyGeneratorX86::getConditionRegister() {
219-
int min = INT_MAX;
220-
int minIndex;
221-
for (unsigned i = 0; i < 8; ++i) {
222-
if (registerUsage[i] < min) {
223-
min = registerUsage[i];
224-
minIndex = i;
225-
}
226-
}
227-
return minIndex;
228-
}
229-
230219
void AssemblyGeneratorX86::traceint(Instruction& instr) {
231220
if (trace) {
232221
asmCode << "\tpush " << regR[instr.dst] << std::endl;
@@ -273,7 +262,7 @@ namespace randomx {
273262
}
274263

275264
void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) {
276-
registerUsage[instr.dst] = i;
265+
registerUsage[instr.dst].lastUsed = i;
277266
if(instr.dst == RegisterNeedsDisplacement)
278267
asmCode << "\tlea " << regR[instr.dst] << ", [" << regR[instr.dst] << "+" << regR[instr.src] << "*" << (1 << (instr.getModShift())) << std::showpos << (int32_t)instr.getImm32() << std::noshowpos << "]" << std::endl;
279268
else
@@ -282,7 +271,7 @@ namespace randomx {
282271
}
283272

284273
void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) {
285-
registerUsage[instr.dst] = i;
274+
registerUsage[instr.dst].lastUsed = i;
286275
if (instr.src != instr.dst) {
287276
genAddressReg(instr);
288277
asmCode << "\tadd " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@@ -294,7 +283,7 @@ namespace randomx {
294283
}
295284

296285
void AssemblyGeneratorX86::h_ISUB_R(Instruction& instr, int i) {
297-
registerUsage[instr.dst] = i;
286+
registerUsage[instr.dst].lastUsed = i;
298287
if (instr.src != instr.dst) {
299288
asmCode << "\tsub " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
300289
}
@@ -305,7 +294,7 @@ namespace randomx {
305294
}
306295

307296
void AssemblyGeneratorX86::h_ISUB_M(Instruction& instr, int i) {
308-
registerUsage[instr.dst] = i;
297+
registerUsage[instr.dst].lastUsed = i;
309298
if (instr.src != instr.dst) {
310299
genAddressReg(instr);
311300
asmCode << "\tsub " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@@ -317,7 +306,7 @@ namespace randomx {
317306
}
318307

319308
void AssemblyGeneratorX86::h_IMUL_R(Instruction& instr, int i) {
320-
registerUsage[instr.dst] = i;
309+
registerUsage[instr.dst].lastUsed = i;
321310
if (instr.src != instr.dst) {
322311
asmCode << "\timul " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
323312
}
@@ -328,7 +317,7 @@ namespace randomx {
328317
}
329318

330319
void AssemblyGeneratorX86::h_IMUL_M(Instruction& instr, int i) {
331-
registerUsage[instr.dst] = i;
320+
registerUsage[instr.dst].lastUsed = i;
332321
if (instr.src != instr.dst) {
333322
genAddressReg(instr);
334323
asmCode << "\timul " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@@ -341,15 +330,15 @@ namespace randomx {
341330

342331
//4 uOPs
343332
void AssemblyGeneratorX86::h_IMULH_R(Instruction& instr, int i) {
344-
registerUsage[instr.dst] = i;
333+
registerUsage[instr.dst].lastUsed = i;
345334
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
346335
asmCode << "\tmul " << regR[instr.src] << std::endl;
347336
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl;
348337
traceint(instr);
349338
}
350339

351340
void AssemblyGeneratorX86::h_IMULH_M(Instruction& instr, int i) {
352-
registerUsage[instr.dst] = i;
341+
registerUsage[instr.dst].lastUsed = i;
353342
if (instr.src != instr.dst) {
354343
genAddressReg(instr, "ecx");
355344
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@@ -364,15 +353,15 @@ namespace randomx {
364353
}
365354

366355
void AssemblyGeneratorX86::h_ISMULH_R(Instruction& instr, int i) {
367-
registerUsage[instr.dst] = i;
356+
registerUsage[instr.dst].lastUsed = i;
368357
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
369358
asmCode << "\timul " << regR[instr.src] << std::endl;
370359
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl;
371360
traceint(instr);
372361
}
373362

374363
void AssemblyGeneratorX86::h_ISMULH_M(Instruction& instr, int i) {
375-
registerUsage[instr.dst] = i;
364+
registerUsage[instr.dst].lastUsed = i;
376365
if (instr.src != instr.dst) {
377366
genAddressReg(instr, "ecx");
378367
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@@ -387,13 +376,13 @@ namespace randomx {
387376
}
388377

389378
void AssemblyGeneratorX86::h_INEG_R(Instruction& instr, int i) {
390-
registerUsage[instr.dst] = i;
379+
registerUsage[instr.dst].lastUsed = i;
391380
asmCode << "\tneg " << regR[instr.dst] << std::endl;
392381
traceint(instr);
393382
}
394383

395384
void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) {
396-
registerUsage[instr.dst] = i;
385+
registerUsage[instr.dst].lastUsed = i;
397386
if (instr.src != instr.dst) {
398387
asmCode << "\txor " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
399388
}
@@ -404,7 +393,7 @@ namespace randomx {
404393
}
405394

406395
void AssemblyGeneratorX86::h_IXOR_M(Instruction& instr, int i) {
407-
registerUsage[instr.dst] = i;
396+
registerUsage[instr.dst].lastUsed = i;
408397
if (instr.src != instr.dst) {
409398
genAddressReg(instr);
410399
asmCode << "\txor " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@@ -416,7 +405,7 @@ namespace randomx {
416405
}
417406

418407
void AssemblyGeneratorX86::h_IROR_R(Instruction& instr, int i) {
419-
registerUsage[instr.dst] = i;
408+
registerUsage[instr.dst].lastUsed = i;
420409
if (instr.src != instr.dst) {
421410
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
422411
asmCode << "\tror " << regR[instr.dst] << ", cl" << std::endl;
@@ -428,7 +417,7 @@ namespace randomx {
428417
}
429418

430419
void AssemblyGeneratorX86::h_IROL_R(Instruction& instr, int i) {
431-
registerUsage[instr.dst] = i;
420+
registerUsage[instr.dst].lastUsed = i;
432421
if (instr.src != instr.dst) {
433422
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
434423
asmCode << "\trol " << regR[instr.dst] << ", cl" << std::endl;
@@ -441,7 +430,7 @@ namespace randomx {
441430

442431
void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) {
443432
if (instr.getImm32() != 0) {
444-
registerUsage[instr.dst] = i;
433+
registerUsage[instr.dst].lastUsed = i;
445434
asmCode << "\tmov rax, " << randomx_reciprocal(instr.getImm32()) << std::endl;
446435
asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl;
447436
traceint(instr);
@@ -453,8 +442,8 @@ namespace randomx {
453442

454443
void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) {
455444
if (instr.src != instr.dst) {
456-
registerUsage[instr.dst] = i;
457-
registerUsage[instr.src] = i;
445+
registerUsage[instr.dst].lastUsed = i;
446+
registerUsage[instr.src].lastUsed = i;
458447
asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
459448
traceint(instr);
460449
}
@@ -541,14 +530,16 @@ namespace randomx {
541530
}
542531

543532
void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) {
544-
int reg = getConditionRegister();
545-
int target = registerUsage[reg] + 1;
533+
int reg = getConditionRegister(registerUsage);
534+
int target = registerUsage[reg].lastUsed + 1;
535+
registerUsage[reg].count++;
546536
int shift = instr.getModCond();
547537
asmCode << "\tadd " << regR[reg] << ", " << (int32_t)(instr.getImm32() | (1 << shift)) << std::endl;
548538
asmCode << "\ttest " << regR[reg] << ", " << (ConditionMask << shift) << std::endl;
549539
asmCode << "\tjz randomx_isn_" << target << std::endl;
550-
for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used
551-
registerUsage[j] = i;
540+
//mark all registers as used
541+
for (unsigned j = 0; j < RegistersCount; ++j) {
542+
registerUsage[j].lastUsed = i;
552543
}
553544
}
554545

src/assembly_generator_x86.hpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ namespace randomx {
4343
void genAddressReg(Instruction&, const char*);
4444
void genAddressRegDst(Instruction&, int);
4545
int32_t genAddressImm(Instruction&);
46-
int getConditionRegister();
4746
void generateCode(Instruction&, int);
4847
void traceint(Instruction&);
4948
void traceflt(Instruction&);
@@ -82,6 +81,6 @@ namespace randomx {
8281

8382
static InstructionGenerator engine[256];
8483
std::stringstream asmCode;
85-
int registerUsage[RegistersCount];
84+
RegisterUsage registerUsage[RegistersCount];
8685
};
8786
}

src/common.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ namespace randomx {
8888
double hi;
8989
};
9090

91+
struct RegisterUsage {
92+
int32_t lastUsed;
93+
int32_t count;
94+
};
95+
9196
constexpr uint32_t ScratchpadL1 = RANDOMX_SCRATCHPAD_L1 / sizeof(int_reg_t);
9297
constexpr uint32_t ScratchpadL2 = RANDOMX_SCRATCHPAD_L2 / sizeof(int_reg_t);
9398
constexpr uint32_t ScratchpadL3 = RANDOMX_SCRATCHPAD_L3 / sizeof(int_reg_t);
@@ -102,6 +107,21 @@ namespace randomx {
102107
constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register
103108
constexpr int RegisterNeedsSib = 4; //x86 r12 register
104109

110+
inline int getConditionRegister(RegisterUsage(&registerUsage)[RegistersCount]) {
111+
int min = INT_MAX;
112+
int minCount = 0;
113+
int minIndex;
114+
//prefer registers that have been used as a condition register fewer times
115+
for (unsigned i = 0; i < RegistersCount; ++i) {
116+
if (registerUsage[i].lastUsed < min || (registerUsage[i].lastUsed == min && registerUsage[i].count < minCount)) {
117+
min = registerUsage[i].lastUsed;
118+
minCount = registerUsage[i].count;
119+
minIndex = i;
120+
}
121+
}
122+
return minIndex;
123+
}
124+
105125
struct MemoryRegisters {
106126
addr_t mx, ma;
107127
uint8_t* memory = nullptr;

0 commit comments

Comments
 (0)