@@ -1277,6 +1277,11 @@ static void prepare_translate(struct jit_state *state)
1277
1277
}
1278
1278
1279
1279
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 ];
1280
1285
static int vm_reg [3 ]; /* enum x64_reg/a64_reg */
1281
1286
1282
1287
static void reset_reg ()
@@ -1310,6 +1315,242 @@ static void store_back(struct jit_state *state)
1310
1315
}
1311
1316
}
1312
1317
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
+
1313
1554
/* Unmap the vm register to the host register. */
1314
1555
static inline void unmap_vm_reg (int idx )
1315
1556
{
@@ -1318,8 +1559,6 @@ static inline void unmap_vm_reg(int idx)
1318
1559
register_map [idx ].vm_reg_idx = -1 ;
1319
1560
}
1320
1561
1321
- #include "reg-alloc.c"
1322
-
1323
1562
static inline void set_vm_reg (int idx , int vm_reg_idx )
1324
1563
{
1325
1564
assert (idx > -1 && idx < n_host_regs );
0 commit comments