The EBB argument splitting may generate concat-split dependencies when it repairs branch arguments in EBBs that have not yet been fully legalized. Add a branch argument simplification step that can resolve these dependency chains. This means that all split and concatenation instructions will be dead after legalization for types that have no legal instructions using them.
126 lines
3.5 KiB
Plaintext
126 lines
3.5 KiB
Plaintext
; Test legalizer's handling of ABI boundaries.
|
|
test legalizer
|
|
isa riscv
|
|
|
|
; regex: V=vx?\d+
|
|
|
|
function int_split_args(i64) -> i64 {
|
|
ebb0(v0: i64):
|
|
; check: $ebb0($(v0l=$V): i32, $(v0h=$V): i32):
|
|
; check: iconcat $v0l, $v0h
|
|
v1 = iadd_imm v0, 1
|
|
; check: $(v1l=$V), $(v1h=$V) = isplit $v1
|
|
; check: return $v1l, $v1h
|
|
return v1
|
|
}
|
|
|
|
function split_call_arg(i32) {
|
|
fn1 = function foo(i64)
|
|
fn2 = function foo(i32, i64)
|
|
ebb0(v0: i32):
|
|
v1 = uextend.i64 v0
|
|
call fn1(v1)
|
|
; check: $(v1l=$V), $(v1h=$V) = isplit $v1
|
|
; check: call $fn1($v1l, $v1h)
|
|
call fn2(v0, v1)
|
|
; check: call $fn2($v0, $V, $V)
|
|
return
|
|
}
|
|
|
|
function split_ret_val() {
|
|
fn1 = function foo() -> i64
|
|
ebb0:
|
|
v1 = call fn1()
|
|
; check: $ebb0:
|
|
; nextln: $(v1l=$V), $(v1h=$V) = call $fn1()
|
|
; check: $(v1new=$V) = iconcat $v1l, $v1h
|
|
; check: $v1 = copy $v1new
|
|
jump ebb1(v1)
|
|
; The v1 copy gets resolved by split::simplify_branch_arguments().
|
|
; check: jump $ebb1($v1new)
|
|
|
|
ebb1(v10: i64):
|
|
jump ebb1(v10)
|
|
}
|
|
|
|
; First return value is fine, second one is expanded.
|
|
function split_ret_val2() {
|
|
fn1 = function foo() -> i32, i64
|
|
ebb0:
|
|
v1, v2 = call fn1()
|
|
; check: $ebb0:
|
|
; nextln: $v1, $(v2l=$V), $(v2h=$V) = call $fn1()
|
|
; check: $(v2new=$V) = iconcat $v2l, $v2h
|
|
jump ebb1(v1, v2)
|
|
; The v2 -> v2new alias is resolved by split::simplify_branch_arguments().
|
|
; check: jump $ebb1($v1, $v2new)
|
|
|
|
ebb1(v9: i32, v10: i64):
|
|
jump ebb1(v9, v10)
|
|
}
|
|
|
|
function int_ext(i8, i8 sext, i8 uext) -> i8 uext {
|
|
ebb0(v1: i8, v2: i8, v3: i8):
|
|
; check: $ebb0($v1: i8, $(v2x=$V): i32, $(v3x=$V): i32):
|
|
; check: ireduce.i8 $v2x
|
|
; check: ireduce.i8 $v3x
|
|
; check: $(v1x=$V) = uextend.i32 $v1
|
|
; check: return $v1x
|
|
return v1
|
|
}
|
|
|
|
; Function produces single return value, still need to copy.
|
|
function ext_ret_val() {
|
|
fn1 = function foo() -> i8 sext
|
|
ebb0:
|
|
v1 = call fn1()
|
|
; check: $ebb0:
|
|
; nextln: $(rv=$V) = call $fn1()
|
|
; check: $(v1new=$V) = ireduce.i8 $rv
|
|
; check: $v1 = copy $v1new
|
|
jump ebb1(v1)
|
|
; The v1 copy gets resolved by split::simplify_branch_arguments().
|
|
; check: jump $ebb1($v1new)
|
|
|
|
ebb1(v10: i8):
|
|
jump ebb1(v10)
|
|
}
|
|
|
|
function vector_split_args(i64x4) -> i64x4 {
|
|
ebb0(v0: i64x4):
|
|
; check: $ebb0($(v0al=$V): i32, $(v0ah=$V): i32, $(v0bl=$V): i32, $(v0bh=$V): i32, $(v0cl=$V): i32, $(v0ch=$V): i32, $(v0dl=$V): i32, $(v0dh=$V): i32):
|
|
; check: $(v0a=$V) = iconcat $v0al, $v0ah
|
|
; check: $(v0b=$V) = iconcat $v0bl, $v0bh
|
|
; check: $(v0ab=$V) = vconcat $v0a, $v0b
|
|
; check: $(v0c=$V) = iconcat $v0cl, $v0ch
|
|
; check: $(v0d=$V) = iconcat $v0dl, $v0dh
|
|
; check: $(v0cd=$V) = vconcat $v0c, $v0d
|
|
; check: $(v0abcd=$V) = vconcat $v0ab, $v0cd
|
|
v1 = iadd v0, v0
|
|
; check: $(v1ab=$V), $(v1cd=$V) = vsplit
|
|
; check: $(v1a=$V), $(v1b=$V) = vsplit $v1ab
|
|
; check: $(v1al=$V), $(v1ah=$V) = isplit $v1a
|
|
; check: $(v1bl=$V), $(v1bh=$V) = isplit $v1b
|
|
; check: $(v1c=$V), $(v1d=$V) = vsplit $v1cd
|
|
; check: $(v1cl=$V), $(v1ch=$V) = isplit $v1c
|
|
; check: $(v1dl=$V), $(v1dh=$V) = isplit $v1d
|
|
; check: return $v1al, $v1ah, $v1bl, $v1bh, $v1cl, $v1ch, $v1dl, $v1dh
|
|
return v1
|
|
}
|
|
|
|
function indirect(i32) {
|
|
sig1 = signature()
|
|
ebb0(v0: i32):
|
|
call_indirect sig1, v0()
|
|
return
|
|
}
|
|
|
|
; The first argument to call_indirect doesn't get altered.
|
|
function indirect_arg(i32, f32x2) {
|
|
sig1 = signature(f32x2)
|
|
ebb0(v0: i32, v1: f32x2):
|
|
call_indirect sig1, v0(v1)
|
|
; check: call_indirect $sig1, $v0($V, $V)
|
|
return
|
|
}
|