Add support for brff/brif and icmp_sp to new x64 backend to support Lucet.
`lucetc` currently *almost*, but not quite, works with the new x64 backend; the only missing piece is support for the particular instructions emitted as part of its prologue stack-check. We do not normally see `brff`, `brif`, or `ifcmp_sp` in CLIF generated by `cranelift-wasm` without the old-backend legalization rules, so these were not supported in the new x64 backend as they were not necessary for Wasm MVP support. Using them resulted in an `unimplemented!()` panic. This PR adds support for `brff` and `brif` analogously to how AArch64 implements them, by pattern-matching the `ifcmp` / `ffcmp` directly. Then `ifcmp_sp` is a straightforward variant of `ifcmp`. Along the way, this also removes the notion of "fallthrough block" from the branch-group lowering method; instead, `fallthrough` instructions are handled as normal branches to their explicitly-provided targets, which (in the original CLIF) match the fallthrough block. The reason for this is that the block reordering done as part of lowering can change the fallthrough block. We were not using `fallthrough` instructions in the output produced by `cranelift-wasm`, so this, too, was not previously caught. With these changes, the `lucetc` crate in Lucet passes all tests with the `x64` feature-flag added to its `cranelift-codegen` dependency.
This commit is contained in:
88
cranelift/filetests/filetests/isa/x64/branches.clif
Normal file
88
cranelift/filetests/filetests/isa/x64/branches.clif
Normal file
@@ -0,0 +1,88 @@
|
||||
test compile
|
||||
target x86_64
|
||||
feature "experimental_x64"
|
||||
|
||||
function %f0(i32, i32) -> i32 {
|
||||
block0(v0: i32, v1: i32):
|
||||
v2 = icmp eq v0, v1
|
||||
brnz v2, block1
|
||||
jump block2
|
||||
; check: cmpl %esi, %edi
|
||||
; nextln: jz label1; j label2
|
||||
|
||||
block1:
|
||||
v3 = iconst.i32 1
|
||||
; check: movl $$1, %eax
|
||||
return v3
|
||||
; check: ret
|
||||
|
||||
block2:
|
||||
v4 = iconst.i32 2
|
||||
; check: movl $$2, %eax
|
||||
return v4
|
||||
; check: ret
|
||||
}
|
||||
|
||||
function %f1(i32, i32) -> i32 {
|
||||
block0(v0: i32, v1: i32):
|
||||
v2 = icmp eq v0, v1
|
||||
brz v2, block1
|
||||
jump block2
|
||||
; check: cmpl %esi, %edi
|
||||
; nextln: jnz label1; j label2
|
||||
|
||||
block1:
|
||||
v3 = iconst.i32 1
|
||||
; check: movl $$1, %eax
|
||||
return v3
|
||||
; check: ret
|
||||
|
||||
block2:
|
||||
v4 = iconst.i32 2
|
||||
; check: movl $$2, %eax
|
||||
return v4
|
||||
; check: ret
|
||||
}
|
||||
|
||||
function %f2(i32, i32) -> i32 {
|
||||
block0(v0: i32, v1: i32):
|
||||
v2 = ifcmp v0, v1
|
||||
brif eq v2, block1
|
||||
jump block2
|
||||
; check: cmpl %esi, %edi
|
||||
; nextln: jz label1; j label2
|
||||
|
||||
block1:
|
||||
v3 = iconst.i32 1
|
||||
; check: movl $$1, %eax
|
||||
return v3
|
||||
; check: ret
|
||||
|
||||
block2:
|
||||
v4 = iconst.i32 2
|
||||
; check: movl $$2, %eax
|
||||
return v4
|
||||
; check: ret
|
||||
}
|
||||
|
||||
function %f3(f32, f32) -> i32 {
|
||||
block0(v0: f32, v1: f32):
|
||||
v2 = ffcmp v0, v1
|
||||
brff eq v2, block1
|
||||
jump block2
|
||||
; check: ucomiss %xmm1, %xmm0
|
||||
; nextln: jp label2
|
||||
; nextln: jnz label2; j label1
|
||||
|
||||
block1:
|
||||
v3 = iconst.i32 1
|
||||
; check: movl $$1, %eax
|
||||
return v3
|
||||
; check: ret
|
||||
|
||||
block2:
|
||||
v4 = iconst.i32 2
|
||||
; check: movl $$2, %eax
|
||||
return v4
|
||||
; check: ret
|
||||
}
|
||||
Reference in New Issue
Block a user