To keep cross-compiling straightforward, Cretonne shouldn't have any behavior that depends on the host. This renames the "Native" calling convention to "SystemV", which has a defined meaning for each target, so that it's clear that the calling convention doesn't change depending on what host Cretonne is running on.
221 lines
5.6 KiB
Plaintext
221 lines
5.6 KiB
Plaintext
test regalloc
|
|
|
|
; Test the spiler on an ISA with few registers.
|
|
; RV32E has 16 registers, where:
|
|
; - %x0 is hardwired to zero.
|
|
; - %x1 is the return address.
|
|
; - %x2 is the stack pointer.
|
|
; - %x3 is the global pointer.
|
|
; - %x4 is the thread pointer.
|
|
; - %x10-%x15 are function arguments.
|
|
;
|
|
; regex: V=v\d+
|
|
; regex: WS=\s+
|
|
|
|
isa riscv enable_e
|
|
|
|
; In straight-line code, the first value defined is spilled.
|
|
; That is in order:
|
|
; 1. The argument v1.
|
|
; 2. The link register.
|
|
; 3. The first computed value, v2
|
|
function %pyramid(i32) -> i32 {
|
|
; check: ss0 = spill_slot 4
|
|
; check: ss1 = spill_slot 4
|
|
; check: ss2 = spill_slot 4
|
|
; not: spill_slot
|
|
ebb0(v1: i32):
|
|
; check: ebb0($(rv1=$V): i32 [%x10], $(rlink=$V): i32 [%x1])
|
|
; check: ,ss0]$WS v1 = spill $rv1
|
|
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
|
; not: spill
|
|
v2 = iadd_imm v1, 12
|
|
; check: $(r1v2=$V) = iadd_imm
|
|
; nextln: ,ss2]$WS v2 = spill $r1v2
|
|
; not: spill
|
|
v3 = iadd_imm v2, 12
|
|
v4 = iadd_imm v3, 12
|
|
v5 = iadd_imm v4, 12
|
|
v6 = iadd_imm v5, 12
|
|
v7 = iadd_imm v6, 12
|
|
v8 = iadd_imm v7, 12
|
|
v9 = iadd_imm v8, 12
|
|
v10 = iadd_imm v9, 12
|
|
v11 = iadd_imm v10, 12
|
|
v12 = iadd_imm v11, 12
|
|
v13 = iadd_imm v12, 12
|
|
v14 = iadd_imm v13, 12
|
|
v33 = iadd v13, v14
|
|
; check: iadd v13
|
|
v32 = iadd v33, v12
|
|
v31 = iadd v32, v11
|
|
v30 = iadd v31, v10
|
|
v29 = iadd v30, v9
|
|
v28 = iadd v29, v8
|
|
v27 = iadd v28, v7
|
|
v26 = iadd v27, v6
|
|
v25 = iadd v26, v5
|
|
v24 = iadd v25, v4
|
|
v23 = iadd v24, v3
|
|
v22 = iadd v23, v2
|
|
; check: $(r2v2=$V) = fill v2
|
|
; check: v22 = iadd v23, $r2v2
|
|
v21 = iadd v22, v1
|
|
; check: $(r2v1=$V) = fill v1
|
|
; check: v21 = iadd v22, $r2v1
|
|
; check: $(rlink2=$V) = fill $link
|
|
return v21
|
|
; check: return v21, $rlink2
|
|
}
|
|
|
|
; All values live across a call must be spilled
|
|
function %across_call(i32) {
|
|
fn0 = function %foo(i32)
|
|
ebb0(v1: i32):
|
|
; check: v1 = spill
|
|
call fn0(v1)
|
|
; check: call fn0
|
|
call fn0(v1)
|
|
; check: fill v1
|
|
; check: call fn0
|
|
return
|
|
}
|
|
|
|
; The same value used for two function arguments.
|
|
function %doubleuse(i32) {
|
|
fn0 = function %xx(i32, i32)
|
|
ebb0(v0: i32):
|
|
; check: $(c=$V) = copy v0
|
|
call fn0(v0, v0)
|
|
; check: call fn0(v0, $c)
|
|
return
|
|
}
|
|
|
|
; The same value used as indirect callee and argument.
|
|
function %doubleuse_icall1(i32) {
|
|
sig0 = (i32) system_v
|
|
ebb0(v0: i32):
|
|
; not:copy
|
|
call_indirect sig0, v0(v0)
|
|
return
|
|
}
|
|
|
|
; The same value used as indirect callee and two arguments.
|
|
function %doubleuse_icall2(i32) {
|
|
sig0 = (i32, i32) system_v
|
|
ebb0(v0: i32):
|
|
; check: $(c=$V) = copy v0
|
|
call_indirect sig0, v0(v0, v0)
|
|
; check: call_indirect sig0, v0(v0, $c)
|
|
return
|
|
}
|
|
|
|
; Two arguments on the stack.
|
|
function %stackargs(i32, i32, i32, i32, i32, i32, i32, i32) -> i32 {
|
|
; check: ss0 = incoming_arg 4
|
|
; check: ss1 = incoming_arg 4, offset 4
|
|
; not: incoming_arg
|
|
ebb0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32, v5: i32, v6: i32, v7: i32):
|
|
; unordered: fill v6
|
|
; unordered: fill v7
|
|
v10 = iadd v6, v7
|
|
return v10
|
|
}
|
|
|
|
; More EBB arguments than registers.
|
|
function %ebbargs(i32) -> i32 {
|
|
ebb0(v1: i32):
|
|
; check: v1 = spill
|
|
v2 = iconst.i32 1
|
|
jump ebb1(v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2)
|
|
|
|
ebb1(v10: i32, v11: i32, v12: i32, v13: i32, v14: i32, v15: i32, v16: i32, v17: i32, v18: i32, v19: i32, v20: i32, v21: i32):
|
|
v22 = iadd v10, v11
|
|
v23 = iadd v22, v12
|
|
v24 = iadd v23, v13
|
|
v25 = iadd v24, v14
|
|
v26 = iadd v25, v15
|
|
v27 = iadd v26, v16
|
|
v28 = iadd v27, v17
|
|
v29 = iadd v28, v18
|
|
v30 = iadd v29, v19
|
|
v31 = iadd v30, v20
|
|
v32 = iadd v31, v21
|
|
v33 = iadd v32, v1
|
|
return v33
|
|
}
|
|
|
|
; Spilling an EBB argument to make room for a branch operand.
|
|
function %brargs(i32) -> i32 {
|
|
ebb0(v1: i32):
|
|
; check: v1 = spill
|
|
v2 = iconst.i32 1
|
|
brnz v1, ebb1(v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2, v2)
|
|
return v1
|
|
|
|
ebb1(v10: i32, v11: i32, v12: i32, v13: i32, v14: i32, v15: i32, v16: i32, v17: i32, v18: i32, v19: i32, v20: i32, v21: i32):
|
|
v22 = iadd v10, v11
|
|
v23 = iadd v22, v12
|
|
v24 = iadd v23, v13
|
|
v25 = iadd v24, v14
|
|
v26 = iadd v25, v15
|
|
v27 = iadd v26, v16
|
|
v28 = iadd v27, v17
|
|
v29 = iadd v28, v18
|
|
v30 = iadd v29, v19
|
|
v31 = iadd v30, v20
|
|
v32 = iadd v31, v21
|
|
v33 = iadd v32, v1
|
|
return v33
|
|
}
|
|
|
|
; In straight-line code, the first value defined is spilled.
|
|
; That is in order:
|
|
; 1. The argument v1.
|
|
; 2. The link register.
|
|
; 3. The first computed value, v2
|
|
function %use_spilled_value(i32) -> i32 {
|
|
; check: ss0 = spill_slot 4
|
|
; check: ss1 = spill_slot 4
|
|
; check: ss2 = spill_slot 4
|
|
ebb0(v1: i32):
|
|
; check: ebb0($(rv1=$V): i32 [%x10], $(rlink=$V): i32 [%x1])
|
|
; check: ,ss0]$WS v1 = spill $rv1
|
|
; nextln: ,ss1]$WS $(link=$V) = spill $rlink
|
|
; not: spill
|
|
v2 = iadd_imm v1, 12
|
|
; check: $(r1v2=$V) = iadd_imm
|
|
; nextln: ,ss2]$WS v2 = spill $r1v2
|
|
v3 = iadd_imm v2, 12
|
|
v4 = iadd_imm v3, 12
|
|
v5 = iadd_imm v4, 12
|
|
v6 = iadd_imm v5, 12
|
|
v7 = iadd_imm v6, 12
|
|
v8 = iadd_imm v7, 12
|
|
v9 = iadd_imm v8, 12
|
|
v10 = iadd_imm v9, 12
|
|
v11 = iadd_imm v10, 12
|
|
v12 = iadd_imm v11, 12
|
|
v13 = iadd_imm v12, 12
|
|
v14 = iadd_imm v13, 12
|
|
|
|
; Here we have maximum register pressure, and v2 has been spilled.
|
|
; What happens if we use it?
|
|
v33 = iadd v2, v14
|
|
v32 = iadd v33, v12
|
|
v31 = iadd v32, v11
|
|
v30 = iadd v31, v10
|
|
v29 = iadd v30, v9
|
|
v28 = iadd v29, v8
|
|
v27 = iadd v28, v7
|
|
v26 = iadd v27, v6
|
|
v25 = iadd v26, v5
|
|
v24 = iadd v25, v4
|
|
v23 = iadd v24, v3
|
|
v22 = iadd v23, v2
|
|
v21 = iadd v22, v1
|
|
v20 = iadd v21, v13
|
|
v19 = iadd v20, v2
|
|
return v21
|
|
}
|