Skip to content

Commit d8a4c40

Browse files
committed
Move "reg-alloc" into "jit.c"
1 parent 551c4d5 commit d8a4c40

File tree

2 files changed

+241
-248
lines changed

2 files changed

+241
-248
lines changed

Diff for: src/jit.c

+241-2
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,11 @@ static void prepare_translate(struct jit_state *state)
12771277
}
12781278

12791279

1280+
static int liveness[N_RV_REGS];
1281+
/* The priority queue of vm registers. The one which has farthest liveness is
1282+
* first.
1283+
*/
1284+
static uint8_t candidate_queue[N_RV_REGS];
12801285
static int vm_reg[3]; /* enum x64_reg/a64_reg */
12811286

12821287
static void reset_reg()
@@ -1310,6 +1315,242 @@ static void store_back(struct jit_state *state)
13101315
}
13111316
}
13121317

1318+
1319+
static inline void liveness_reset()
1320+
{
1321+
memset(liveness, 0xff, sizeof(liveness));
1322+
}
1323+
1324+
static inline void candidate_queue_init()
1325+
{
1326+
for (int i = 0; i < N_RV_REGS; i++) {
1327+
candidate_queue[i] = i;
1328+
}
1329+
}
1330+
1331+
static int liveness_cmp(const void *l, const void *r)
1332+
{
1333+
return liveness[*(uint8_t *) l] - liveness[*(uint8_t *) r];
1334+
}
1335+
1336+
/* TODO: this function could be generated by "tools/gen-jit-template.py" */
1337+
static inline void liveness_calc(block_t *block)
1338+
{
1339+
uint32_t idx;
1340+
rv_insn_t *ir;
1341+
1342+
/* follow the order of operator in "src/rc32_template.c" */
1343+
for (idx = 0, ir = block->ir_head; idx < block->n_insn;
1344+
idx++, ir = ir->next) {
1345+
switch (ir->opcode) {
1346+
case rv_insn_nop:
1347+
case rv_insn_lui:
1348+
case rv_insn_auipc:
1349+
case rv_insn_jal:
1350+
break;
1351+
case rv_insn_jalr:
1352+
liveness[ir->rs1] = idx;
1353+
break;
1354+
case rv_insn_beq:
1355+
case rv_insn_bne:
1356+
case rv_insn_blt:
1357+
case rv_insn_bge:
1358+
case rv_insn_bltu:
1359+
case rv_insn_bgeu:
1360+
liveness[ir->rs1] = idx;
1361+
liveness[ir->rs2] = idx;
1362+
break;
1363+
case rv_insn_lb:
1364+
case rv_insn_lh:
1365+
case rv_insn_lw:
1366+
case rv_insn_lbu:
1367+
case rv_insn_lhu:
1368+
liveness[ir->rs1] = idx;
1369+
break;
1370+
case rv_insn_sb:
1371+
case rv_insn_sh:
1372+
case rv_insn_sw:
1373+
liveness[ir->rs1] = idx;
1374+
break;
1375+
case rv_insn_addi:
1376+
case rv_insn_slti:
1377+
case rv_insn_sltiu:
1378+
case rv_insn_xori:
1379+
case rv_insn_ori:
1380+
case rv_insn_andi:
1381+
case rv_insn_slli:
1382+
case rv_insn_srli:
1383+
case rv_insn_srai:
1384+
liveness[ir->rs1] = idx;
1385+
break;
1386+
case rv_insn_add:
1387+
case rv_insn_sub:
1388+
case rv_insn_sll:
1389+
case rv_insn_slt:
1390+
case rv_insn_sltu:
1391+
case rv_insn_xor:
1392+
case rv_insn_srl:
1393+
case rv_insn_sra:
1394+
case rv_insn_or:
1395+
case rv_insn_and:
1396+
liveness[ir->rs1] = idx;
1397+
liveness[ir->rs2] = idx;
1398+
break;
1399+
case rv_insn_ecall:
1400+
case rv_insn_ebreak:
1401+
break;
1402+
#if RV32_HAS(EXT_M)
1403+
case rv_insn_mul:
1404+
case rv_insn_mulh:
1405+
case rv_insn_mulhsu:
1406+
case rv_insn_mulhu:
1407+
case rv_insn_div:
1408+
case rv_insn_divu:
1409+
case rv_insn_rem:
1410+
case rv_insn_remu:
1411+
liveness[ir->rs1] = idx;
1412+
liveness[ir->rs2] = idx;
1413+
break;
1414+
#endif
1415+
#if RV32_HAS(EXT_C)
1416+
case rv_insn_caddi4spn:
1417+
liveness[rv_reg_sp] = idx;
1418+
break;
1419+
case rv_insn_clw:
1420+
liveness[ir->rs1] = idx;
1421+
break;
1422+
case rv_insn_csw:
1423+
liveness[ir->rs1] = idx;
1424+
break;
1425+
case rv_insn_cnop:
1426+
break;
1427+
case rv_insn_caddi:
1428+
liveness[ir->rd] = idx;
1429+
break;
1430+
case rv_insn_cjal:
1431+
case rv_insn_cli:
1432+
case rv_insn_clui:
1433+
break;
1434+
case rv_insn_caddi16sp:
1435+
liveness[ir->rd] = idx;
1436+
break;
1437+
case rv_insn_csrli:
1438+
case rv_insn_csrai:
1439+
case rv_insn_candi:
1440+
liveness[ir->rs1] = idx;
1441+
break;
1442+
case rv_insn_csub:
1443+
case rv_insn_cxor:
1444+
case rv_insn_cor:
1445+
case rv_insn_cand:
1446+
liveness[ir->rs1] = idx;
1447+
liveness[ir->rs2] = idx;
1448+
break;
1449+
case rv_insn_cj:
1450+
break;
1451+
case rv_insn_cbeqz:
1452+
case rv_insn_cbnez:
1453+
liveness[ir->rs1] = idx;
1454+
break;
1455+
case rv_insn_cslli:
1456+
liveness[ir->rd] = idx;
1457+
break;
1458+
case rv_insn_clwsp:
1459+
liveness[rv_reg_sp] = idx;
1460+
break;
1461+
case rv_insn_cjr:
1462+
liveness[ir->rs1] = idx;
1463+
break;
1464+
case rv_insn_cmv:
1465+
liveness[ir->rs2] = idx;
1466+
break;
1467+
case rv_insn_cebreak:
1468+
break;
1469+
case rv_insn_cjalr:
1470+
liveness[ir->rs1] = idx;
1471+
break;
1472+
case rv_insn_cadd:
1473+
liveness[ir->rs1] = idx;
1474+
liveness[ir->rs2] = idx;
1475+
break;
1476+
case rv_insn_cswsp:
1477+
liveness[rv_reg_sp] = idx;
1478+
liveness[ir->rs2] = idx;
1479+
break;
1480+
#endif
1481+
case rv_insn_fuse1:
1482+
for (int i = 0; i < ir->imm2; i++) {
1483+
liveness[ir->fuse[i].rd] = idx;
1484+
}
1485+
break;
1486+
case rv_insn_fuse2:
1487+
liveness[ir->rs1] = idx;
1488+
break;
1489+
case rv_insn_fuse3:
1490+
for (int i = 0; i < ir->imm2; i++) {
1491+
liveness[ir->fuse[i].rs1] = idx;
1492+
liveness[ir->fuse[i].rs2] = idx;
1493+
}
1494+
break;
1495+
case rv_insn_fuse4:
1496+
case rv_insn_fuse7:
1497+
for (int i = 0; i < ir->imm2; i++) {
1498+
liveness[ir->fuse[i].rs1] = idx;
1499+
}
1500+
break;
1501+
case rv_insn_fuse5:
1502+
case rv_insn_fuse6:
1503+
break;
1504+
default:
1505+
__UNREACHABLE;
1506+
}
1507+
}
1508+
1509+
candidate_queue_init();
1510+
qsort(candidate_queue, N_RV_REGS, sizeof(uint8_t), liveness_cmp);
1511+
}
1512+
1513+
static inline void regs_refresh(int idx)
1514+
{
1515+
for (int i = 0; i < n_host_regs; i++) {
1516+
if (register_map[i].vm_reg_idx == -1)
1517+
continue;
1518+
if (liveness[register_map[i].vm_reg_idx] < idx)
1519+
register_map[i].alive = false;
1520+
}
1521+
}
1522+
1523+
/* return the index in the register_map */
1524+
static inline int reg_pick(int reserved)
1525+
{
1526+
/* pick an available register */
1527+
for (int i = 0; i < n_host_regs; i++) {
1528+
if (register_map[i].reg_idx == reserved)
1529+
continue;
1530+
if (!register_map[i].alive)
1531+
return i;
1532+
}
1533+
1534+
/* If registers are exhausted, pick the one which has farthest liveness. */
1535+
int idx = -1;
1536+
for (int i = 0; i < N_RV_REGS; i++) {
1537+
uint8_t candidate = candidate_queue[i];
1538+
for (int j = 0; j < n_host_regs; j++) {
1539+
if (register_map[j].reg_idx == reserved)
1540+
continue;
1541+
if (register_map[j].vm_reg_idx == candidate) {
1542+
idx = j;
1543+
goto end_pick_reg;
1544+
}
1545+
}
1546+
}
1547+
__UNREACHABLE;
1548+
1549+
end_pick_reg:
1550+
assert(idx > -1 && idx < n_host_regs);
1551+
return idx;
1552+
}
1553+
13131554
/* Unmap the vm register to the host register. */
13141555
static inline void unmap_vm_reg(int idx)
13151556
{
@@ -1318,8 +1559,6 @@ static inline void unmap_vm_reg(int idx)
13181559
register_map[idx].vm_reg_idx = -1;
13191560
}
13201561

1321-
#include "reg-alloc.c"
1322-
13231562
static inline void set_vm_reg(int idx, int vm_reg_idx)
13241563
{
13251564
assert(idx > -1 && idx < n_host_regs);

0 commit comments

Comments
 (0)