在 Port mono RISCV 的过程中发现了一些可以优化 / 可能有问题的点,就此记录下来,未来可能会处理。
1. Load Imm 的实现:
在函数 mono_riscv_emit_imm
中,有一段代码被用来加载超过 32 位的立即数,很 tricky。
后期要是优化的话,参考 LLVM 中的实现使用了位移运算指令。
- /*
- * This is not pretty, but RV64I doesn't make it easy to load constants.
- * Need to figure out something better.
- */
- riscv_jal (code, rd, sizeof (guint64));
- *(guint64 *) code = imm;
- code += sizeof (guint64);
- riscv_ld (code, rd, rd, 0);
2. 会分配 Zero(X0)寄存器
C# 源码如下
- namespace HelloWorld
- {
- class Program
- {
- static void Main()
- {
- int a = 0;
- }
- }
- }
CIL 如下
- iconst R59 <- [0]
- store_membase_reg [s0 + 0xfffffffffffffff0] <- R59
- il_seq_point intr il: 0x0
- load_membase R44 <- [s0 + 0xfffffffffffffff8]
- load_membase R48 <- [R44 + 0x8]
- load_membase R49 <- [s0 + 0xfffffffffffffff8]
- load_membase R50 <- [R49 + 0x0]
- add_imm R51 <- s0 [-16]
- add_imm R52 <- s0 [-32]
- add_imm R53 <- s0 [-40]
- add_imm R54 <- s0 [-48]
- add_imm R55 <- s0 [-56]
- add_imm R56 <- R48 [0]
- voidcall_reg R50 clobbers: c
- il_seq_point il: 0x18
- load_membase ra <- [s0 + 0xfffffffffffffff0]
- il_seq_point intr il: 0x19
接着 mono 会进行基于线性扫描分配寄存器。
liveness 如下:
- liveness: ra [16 - 16]
- liveness: s0 [2 - 0]
- liveness: R44 [4 - 4]
- liveness: R48 [5 - 5]
- liveness: R49 [6 - 6]
- liveness: R50 [7 - 7]
- liveness: R51 [8 - 8]
- liveness: R52 [9 - 9]
- liveness: R53 [10 - 10]
- liveness: R54 [11 - 11]
- liveness: R55 [12 - 12]
- liveness: R56 [13 - 13]
分配结果如下:
- processing: 17 il_seq_point intr il: 0x19
- 17 il_seq_point intr il: 0x19
- processing: 16 load_membase ra <- [s0 + 0xfffffffffffffff0]
- 16 load_membase ra <- [s0 + 0xfffffffffffffff0]
- processing: 15 il_seq_point il: 0x18
- 15 il_seq_point il: 0x18
- processing: 14 voidcall_reg R50 clobbers: c
- assigned arg reg zero to R51
- assigned arg reg a0 to R52
- assigned arg reg a1 to R53
- assigned arg reg a2 to R54
- assigned arg reg a3 to R55
- assigned arg reg a4 to R56
- assigned sreg1 a5 to R50
- 14 voidcall_reg a5 clobbers: c
- processing: 13 add_imm R56 <- R48 [0]
- assigned dreg a4 to dest R56
- freeable a4 (R56) (born in 13)
- assigned sreg1 a4 to R48
- 13 add_imm a4 <- a4 [0]
- processing: 12 add_imm R55 <- s0 [-56]
- assigned dreg a3 to dest R55
- freeable a3 (R55) (born in 12)
- 12 add_imm a3 <- s0 [-56]
- processing: 11 add_imm R54 <- s0 [-48]
- assigned dreg a2 to dest R54
- freeable a2 (R54) (born in 11)
- 11 add_imm a2 <- s0 [-48]
- processing: 10 add_imm R53 <- s0 [-40]
- assigned dreg a1 to dest R53
- freeable a1 (R53) (born in 10)
- 10 add_imm a1 <- s0 [-40]
- processing: 9 add_imm R52 <- s0 [-32]
- assigned dreg a0 to dest R52
- freeable a0 (R52) (born in 9)
- 9 add_imm a0 <- s0 [-32]
- processing: 8 add_imm R51 <- s0 [-16]
- assigned dreg zero to dest R51
- freeable zero (R51) (born in 8)
- 8 add_imm zero <- s0 [-16]
- processing: 7 load_membase R50 <- [R49 + 0x0]
- assigned dreg a5 to dest R50
- freeable a5 (R50) (born in 7)
- assigned sreg1 a0 to R49
- 7 load_membase a5 <- [a0 + 0x0]
- processing: 6 load_membase R49 <- [s0 + 0xfffffffffffffff8]
- assigned dreg a0 to dest R49
- freeable a0 (R49) (born in 6)
- 6 load_membase a0 <- [s0 + 0xfffffffffffffff8]
- processing: 5 load_membase R48 <- [R44 + 0x8]
- assigned dreg a4 to dest R48
- freeable a4 (R48) (born in 5)
- assigned sreg1 a0 to R44
- 5 load_membase a4 <- [a0 + 0x8]
- processing: 4 load_membase R44 <- [s0 + 0xfffffffffffffff8]
- assigned dreg a0 to dest R44
- freeable a0 (R44) (born in 4)
- 4 load_membase a0 <- [s0 + 0xfffffffffffffff8]
- processing: 3 il_seq_point intr il: 0x0
- 3 il_seq_point intr il: 0x0
- processing: 2 store_membase_reg [s0 + 0xfffffffffffffff0] <- R59
- assigned sreg1 a0 to R59
- 2 store_membase_reg [s0 + 0xfffffffffffffff0] <- a0
- processing: 1 iconst R59 <- [0]
- assigned dreg a0 to dest R59
- freeable a0 (R59) (born in 1)
- 1 iconst a0 <- [0]
R51
被分配了 zero
寄存器,从 IR 来看,R51 应该是一个参数寄存器 ax
,被用来给之后的 voidcall_reg
传参。