在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
传参。