Files
wazero/internal/engine/wazevo/backend/backend_test.go
Takeshi Yoneda 48327d90ba wazevo(regalloc): makes coloring faster (#1789)
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
2023-10-16 19:46:10 +09:00

2139 lines
41 KiB
Go

package backend_test
import (
"context"
"fmt"
"os"
"runtime"
"testing"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64"
"github.com/tetratelabs/wazero/internal/engine/wazevo/frontend"
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
"github.com/tetratelabs/wazero/internal/engine/wazevo/testcases"
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
"github.com/tetratelabs/wazero/internal/testing/require"
"github.com/tetratelabs/wazero/internal/wasm"
)
func TestMain(m *testing.M) {
if runtime.GOARCH != "arm64" {
os.Exit(0)
}
os.Exit(m.Run())
}
func newMachine() backend.Machine {
switch runtime.GOARCH {
case "arm64":
return arm64.NewBackend()
default:
panic("unsupported architecture")
}
}
func TestE2E(t *testing.T) {
const verbose = false
type testCase struct {
name string
m *wasm.Module
targetIndex uint32
afterLoweringARM64, afterFinalizeARM64 string
// TODO: amd64.
}
for _, tc := range []testCase{
{
name: "empty", m: testcases.Empty.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "selects", m: testcases.Selects.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
subs xzr, x4, x5
csel w0, w2, w3, eq
subs wzr, w3, wzr
csel x1, x4, x5, ne
fcmp d2, d3
fcsel s8, s0, s1, gt
fcmp s0, s1
fcsel d1, d2, d3, ne
mov v0.8b, v8.8b
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "consts", m: testcases.Constants.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
ldr d5?, #8; b 16; data.f64 64.000000
mov v1.8b, v5?.8b
ldr s4?, #8; b 8; data.f32 32.000000
mov v0.8b, v4?.8b
orr x3?, xzr, #0x2
mov x1, x3?
orr w2?, wzr, #0x1
mov x0, x2?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
ldr d1, #8; b 16; data.f64 64.000000
ldr s0, #8; b 8; data.f32 32.000000
orr x1, xzr, #0x2
orr w0, wzr, #0x1
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "add sub params return", m: testcases.AddSubParamsReturn.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
add w4?, w2?, w3?
sub w5?, w4?, w2?
mov x0, x5?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
add w8, w2, w3
sub w0, w8, w2
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "locals params", m: testcases.LocalsParams.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov v3?.8b, v0.8b
mov v4?.8b, v1.8b
add x5?, x2?, x2?
sub x6?, x5?, x2?
fadd s7?, s3?, s3?
fsub s8?, s7?, s3?
fmul s9?, s8?, s3?
fdiv s10?, s9?, s3?
fmax s11?, s10?, s3?
fmin s12?, s11?, s3?
fadd d13?, d4?, d4?
fsub d14?, d13?, d4?
fmul d15?, d14?, d4?
fdiv d16?, d15?, d4?
fmax d17?, d16?, d4?
fmin d18?, d17?, d4?
mov v1.8b, v18?.8b
mov v0.8b, v12?.8b
mov x0, x6?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
add x8, x2, x2
sub x0, x8, x2
fadd s8, s0, s0
fsub s8, s8, s0
fmul s8, s8, s0
fdiv s8, s8, s0
fmax s8, s8, s0
fmin s0, s8, s0
fadd d8, d1, d1
fsub d8, d8, d1
fmul d8, d8, d1
fdiv d8, d8, d1
fmax d8, d8, d1
fmin d1, d8, d1
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "local_param_return", m: testcases.LocalParamReturn.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, xzr
mov x1, x3?
mov x0, x2?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x1, xzr
mov x0, x2
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "swap_param_and_return", m: testcases.SwapParamAndReturn.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
mov x1, x2?
mov x0, x3?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x1, x2
mov x0, x3
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "swap_params_and_return", m: testcases.SwapParamsAndReturn.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
L2 (SSA Block: blk1):
mov x1, x2?
mov x0, x3?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
mov x1, x2
mov x0, x3
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "block_br", m: testcases.BlockBr.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
L2 (SSA Block: blk1):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "block_br_if", m: testcases.BlockBrIf.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x3?, xzr
cbz w3?, (L2)
L3 (SSA Block: blk1):
ret
L2 (SSA Block: blk2):
movz x4?, #0x3, lsl 0
str w4?, [x0?]
mov x5?, sp
str x5?, [x0?, #0x38]
adr x6?, #0x0
str x6?, [x0?, #0x30]
exit_sequence x0?
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, xzr
cbz w8, #0x10 L2
L3 (SSA Block: blk1):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L2 (SSA Block: blk2):
movz x8, #0x3, lsl 0
str w8, [x0]
mov x8, sp
str x8, [x0, #0x38]
adr x8, #0x0
str x8, [x0, #0x30]
exit_sequence x0
`,
},
{
name: "loop_br", m: testcases.LoopBr.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
L2 (SSA Block: blk1):
b L2
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
b #0x0 (L2)
`,
},
{
name: "loop_with_param_results", m: testcases.LoopBrWithParamResults.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
L2 (SSA Block: blk1):
orr w5?, wzr, #0x1
cbz w5?, (L3)
L4 (SSA Block: blk4):
b L2
L3 (SSA Block: blk3):
L5 (SSA Block: blk2):
mov x0, x2?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
orr w8, wzr, #0x1
cbz w8, #0x8 L3
L4 (SSA Block: blk4):
b #-0x8 (L2)
L3 (SSA Block: blk3):
L5 (SSA Block: blk2):
mov x0, x2
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "loop_br_if", m: testcases.LoopBrIf.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
L2 (SSA Block: blk1):
orr w3?, wzr, #0x1
cbz w3?, (L3)
L4 (SSA Block: blk4):
b L2
L3 (SSA Block: blk3):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
orr w8, wzr, #0x1
cbz w8, #0x8 L3
L4 (SSA Block: blk4):
b #-0x8 (L2)
L3 (SSA Block: blk3):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "block_block_br", m: testcases.BlockBlockBr.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
L2 (SSA Block: blk1):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "if_without_else", m: testcases.IfWithoutElse.Module,
// Note: The block of "b L4" seems redundant, but it is needed when we need to insert return value preparations.
// So we cannot have the general optimization on this kind of redundant branch elimination before register allocations.
// Instead, we can do it during the code generation phase where we actually resolve the label offsets.
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x3?, xzr
cbnz w3?, L2
L3 (SSA Block: blk2):
b L4
L2 (SSA Block: blk1):
L4 (SSA Block: blk3):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, xzr
cbnz w8, #0x8 (L2)
L3 (SSA Block: blk2):
b #0x4 (L4)
L2 (SSA Block: blk1):
L4 (SSA Block: blk3):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "if_else", m: testcases.IfElse.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x3?, xzr
cbnz w3?, L2
L3 (SSA Block: blk2):
ret
L2 (SSA Block: blk1):
L4 (SSA Block: blk3):
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, xzr
cbnz w8, #0x10 (L2)
L3 (SSA Block: blk2):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L2 (SSA Block: blk1):
L4 (SSA Block: blk3):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "single_predecessor_local_refs", m: testcases.SinglePredecessorLocalRefs.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x4?, xzr
cbnz w4?, L2
L3 (SSA Block: blk2):
L4 (SSA Block: blk3):
mov x2?, xzr
mov x0, x2?
ret
L2 (SSA Block: blk1):
mov x3?, xzr
mov x0, x3?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, xzr
cbnz w8, #0x14 (L2)
L3 (SSA Block: blk2):
L4 (SSA Block: blk3):
mov x0, xzr
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L2 (SSA Block: blk1):
mov x0, xzr
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "multi_predecessor_local_ref", m: testcases.MultiPredecessorLocalRef.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
cbnz w2?, L2
L3 (SSA Block: blk2):
mov x4?, x3?
b L4
L2 (SSA Block: blk1):
mov x4?, x2?
L4 (SSA Block: blk3):
mov x0, x4?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
cbnz w2, #0xc (L2)
L3 (SSA Block: blk2):
mov x0, x3
b #0x8 (L4)
L2 (SSA Block: blk1):
mov x0, x2
L4 (SSA Block: blk3):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "reference_value_from_unsealed_block", m: testcases.ReferenceValueFromUnsealedBlock.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
L2 (SSA Block: blk1):
mov x0, x2?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
mov x0, x2
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "reference_value_from_unsealed_block2", m: testcases.ReferenceValueFromUnsealedBlock2.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
L2 (SSA Block: blk1):
cbz w2?, (L3)
L4 (SSA Block: blk5):
b L2
L3 (SSA Block: blk4):
L5 (SSA Block: blk3):
L6 (SSA Block: blk2):
mov x3?, xzr
mov x0, x3?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
L2 (SSA Block: blk1):
cbz w2, #0x8 L3
L4 (SSA Block: blk5):
b #-0x4 (L2)
L3 (SSA Block: blk4):
L5 (SSA Block: blk3):
L6 (SSA Block: blk2):
mov x0, xzr
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "reference_value_from_unsealed_block3", m: testcases.ReferenceValueFromUnsealedBlock3.Module,
// TODO: we should be able to invert cbnz in so that L2 can end with fallthrough. investigate builder.LayoutBlocks function.
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x2?
L2 (SSA Block: blk1):
cbnz w3?, L4
b L3
L4 (SSA Block: blk5):
ret
L3 (SSA Block: blk4):
L5 (SSA Block: blk3):
orr w3?, wzr, #0x1
b L2
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, x2
L2 (SSA Block: blk1):
cbnz w8, #0x8 (L4)
b #0x10 (L3)
L4 (SSA Block: blk5):
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L3 (SSA Block: blk4):
L5 (SSA Block: blk3):
orr w8, wzr, #0x1
b #-0x18 (L2)
`,
},
{
name: "call", m: testcases.Call.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
bl f1
mov x2?, x0
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
mov x2, x2?
movz w3?, #0x5, lsl 0
mov x3, x3?
bl f2
mov x4?, x0
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
mov x2, x4?
bl f3
mov x5?, x0
mov x6?, x1
mov x1, x6?
mov x0, x5?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
sub sp, sp, #0x10
orr x27, xzr, #0x10
str x27, [sp, #-0x10]!
mov x9, x0
mov x8, x1
str x8, [x9, #0x8]
mov x0, x9
mov x1, x8
str x9, [sp, #0x10]
str x8, [sp, #0x18]
bl f1
ldr x8, [sp, #0x18]
ldr x9, [sp, #0x10]
mov x2, x0
str x8, [x9, #0x8]
mov x0, x9
mov x1, x8
movz w3, #0x5, lsl 0
str x9, [sp, #0x10]
str x8, [sp, #0x18]
bl f2
ldr x8, [sp, #0x18]
ldr x9, [sp, #0x10]
mov x2, x0
str x8, [x9, #0x8]
mov x0, x9
mov x1, x8
bl f3
add sp, sp, #0x10
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "call_many_params", m: testcases.CallManyParams.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
mov x2?, x2
mov x3?, x3
mov v4?.8b, v0.8b
mov v5?.8b, v1.8b
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
mov x2, x2?
mov x3, x3?
mov v0.8b, v4?.8b
mov v1.8b, v5?.8b
mov x4, x2?
mov x5, x3?
mov v2.8b, v4?.8b
mov v3.8b, v5?.8b
mov x6, x2?
mov x7, x3?
mov v4.8b, v4?.8b
mov v5.8b, v5?.8b
str w2?, [sp, #-0xd0]
str x3?, [sp, #-0xc8]
mov v6.8b, v4?.8b
mov v7.8b, v5?.8b
str w2?, [sp, #-0xc0]
str x3?, [sp, #-0xb8]
str s4?, [sp, #-0xb0]
str d5?, [sp, #-0xa8]
str w2?, [sp, #-0xa0]
str x3?, [sp, #-0x98]
str s4?, [sp, #-0x90]
str d5?, [sp, #-0x88]
str w2?, [sp, #-0x80]
str x3?, [sp, #-0x78]
str s4?, [sp, #-0x70]
str d5?, [sp, #-0x68]
str w2?, [sp, #-0x60]
str x3?, [sp, #-0x58]
str s4?, [sp, #-0x50]
str d5?, [sp, #-0x48]
str w2?, [sp, #-0x40]
str x3?, [sp, #-0x38]
str s4?, [sp, #-0x30]
str d5?, [sp, #-0x28]
str w2?, [sp, #-0x20]
str x3?, [sp, #-0x18]
str s4?, [sp, #-0x10]
str d5?, [sp, #-0x8]
bl f1
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, x2
mov x9, x3
mov v8.8b, v0.8b
mov v9.8b, v1.8b
str x1, [x0, #0x8]
mov x2, x8
mov x3, x9
mov v0.8b, v8.8b
mov v1.8b, v9.8b
mov x4, x8
mov x5, x9
mov v2.8b, v8.8b
mov v3.8b, v9.8b
mov x6, x8
mov x7, x9
mov v4.8b, v8.8b
mov v5.8b, v9.8b
str w8, [sp, #-0xd0]
str x9, [sp, #-0xc8]
mov v6.8b, v8.8b
mov v7.8b, v9.8b
str w8, [sp, #-0xc0]
str x9, [sp, #-0xb8]
str s8, [sp, #-0xb0]
str d9, [sp, #-0xa8]
str w8, [sp, #-0xa0]
str x9, [sp, #-0x98]
str s8, [sp, #-0x90]
str d9, [sp, #-0x88]
str w8, [sp, #-0x80]
str x9, [sp, #-0x78]
str s8, [sp, #-0x70]
str d9, [sp, #-0x68]
str w8, [sp, #-0x60]
str x9, [sp, #-0x58]
str s8, [sp, #-0x50]
str d9, [sp, #-0x48]
str w8, [sp, #-0x40]
str x9, [sp, #-0x38]
str s8, [sp, #-0x30]
str d9, [sp, #-0x28]
str w8, [sp, #-0x20]
str x9, [sp, #-0x18]
str s8, [sp, #-0x10]
str d9, [sp, #-0x8]
bl f1
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "call_many_returns", m: testcases.CallManyReturns.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
mov x2?, x2
mov x3?, x3
mov v4?.8b, v0.8b
mov v5?.8b, v1.8b
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
mov x2, x2?
mov x3, x3?
mov v0.8b, v4?.8b
mov v1.8b, v5?.8b
bl f1
mov x6?, x0
mov x7?, x1
mov v8?.8b, v0.8b
mov v9?.8b, v1.8b
mov x10?, x2
mov x11?, x3
mov v12?.8b, v2.8b
mov v13?.8b, v3.8b
mov x14?, x4
mov x15?, x5
mov v16?.8b, v4.8b
mov v17?.8b, v5.8b
mov x18?, x6
mov x19?, x7
mov v20?.8b, v6.8b
mov v21?.8b, v7.8b
ldr w22?, [sp, #-0xc0]
ldr x23?, [sp, #-0xb8]
ldr s24?, [sp, #-0xb0]
ldr d25?, [sp, #-0xa8]
ldr w26?, [sp, #-0xa0]
ldr x27?, [sp, #-0x98]
ldr s28?, [sp, #-0x90]
ldr d29?, [sp, #-0x88]
ldr w30?, [sp, #-0x80]
ldr x31?, [sp, #-0x78]
ldr s32?, [sp, #-0x70]
ldr d33?, [sp, #-0x68]
ldr w34?, [sp, #-0x60]
ldr x35?, [sp, #-0x58]
ldr s36?, [sp, #-0x50]
ldr d37?, [sp, #-0x48]
ldr w38?, [sp, #-0x40]
ldr x39?, [sp, #-0x38]
ldr s40?, [sp, #-0x30]
ldr d41?, [sp, #-0x28]
ldr w42?, [sp, #-0x20]
ldr x43?, [sp, #-0x18]
ldr s44?, [sp, #-0x10]
ldr d45?, [sp, #-0x8]
str d45?, [#ret_space, #0xb8]
str s44?, [#ret_space, #0xb0]
str x43?, [#ret_space, #0xa8]
str w42?, [#ret_space, #0xa0]
str d41?, [#ret_space, #0x98]
str s40?, [#ret_space, #0x90]
str x39?, [#ret_space, #0x88]
str w38?, [#ret_space, #0x80]
str d37?, [#ret_space, #0x78]
str s36?, [#ret_space, #0x70]
str x35?, [#ret_space, #0x68]
str w34?, [#ret_space, #0x60]
str d33?, [#ret_space, #0x58]
str s32?, [#ret_space, #0x50]
str x31?, [#ret_space, #0x48]
str w30?, [#ret_space, #0x40]
str d29?, [#ret_space, #0x38]
str s28?, [#ret_space, #0x30]
str x27?, [#ret_space, #0x28]
str w26?, [#ret_space, #0x20]
str d25?, [#ret_space, #0x18]
str s24?, [#ret_space, #0x10]
str x23?, [#ret_space, #0x8]
str w22?, [#ret_space, #0x0]
mov v7.8b, v21?.8b
mov v6.8b, v20?.8b
mov x7, x19?
mov x6, x18?
mov v5.8b, v17?.8b
mov v4.8b, v16?.8b
mov x5, x15?
mov x4, x14?
mov v3.8b, v13?.8b
mov v2.8b, v12?.8b
mov x3, x11?
mov x2, x10?
mov v1.8b, v9?.8b
mov v0.8b, v8?.8b
mov x1, x7?
mov x0, x6?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
orr x27, xzr, #0xc0
sub sp, sp, x27
stp x30, x27, [sp, #-0x10]!
str x19, [sp, #-0x10]!
str x20, [sp, #-0x10]!
str q18, [sp, #-0x10]!
str q19, [sp, #-0x10]!
orr x27, xzr, #0x40
str x27, [sp, #-0x10]!
str x1, [x0, #0x8]
bl f1
ldr w20, [sp, #-0xc0]
ldr x19, [sp, #-0xb8]
ldr s19, [sp, #-0xb0]
ldr d18, [sp, #-0xa8]
ldr w17, [sp, #-0xa0]
ldr x16, [sp, #-0x98]
ldr s17, [sp, #-0x90]
ldr d16, [sp, #-0x88]
ldr w15, [sp, #-0x80]
ldr x14, [sp, #-0x78]
ldr s15, [sp, #-0x70]
ldr d14, [sp, #-0x68]
ldr w13, [sp, #-0x60]
ldr x12, [sp, #-0x58]
ldr s13, [sp, #-0x50]
ldr d12, [sp, #-0x48]
ldr w11, [sp, #-0x40]
ldr x10, [sp, #-0x38]
ldr s11, [sp, #-0x30]
ldr d10, [sp, #-0x28]
ldr w9, [sp, #-0x20]
ldr x8, [sp, #-0x18]
ldr s9, [sp, #-0x10]
ldr d8, [sp, #-0x8]
str d8, [sp, #0x118]
str s9, [sp, #0x110]
str x8, [sp, #0x108]
str w9, [sp, #0x100]
str d10, [sp, #0xf8]
str s11, [sp, #0xf0]
str x10, [sp, #0xe8]
str w11, [sp, #0xe0]
str d12, [sp, #0xd8]
str s13, [sp, #0xd0]
str x12, [sp, #0xc8]
str w13, [sp, #0xc0]
str d14, [sp, #0xb8]
str s15, [sp, #0xb0]
str x14, [sp, #0xa8]
str w15, [sp, #0xa0]
str d16, [sp, #0x98]
str s17, [sp, #0x90]
str x16, [sp, #0x88]
str w17, [sp, #0x80]
str d18, [sp, #0x78]
str s19, [sp, #0x70]
str x19, [sp, #0x68]
str w20, [sp, #0x60]
add sp, sp, #0x10
ldr q19, [sp], #0x10
ldr q18, [sp], #0x10
ldr x20, [sp], #0x10
ldr x19, [sp], #0x10
ldr x30, [sp], #0x10
add sp, sp, #0xc0
ret
`,
},
{
name: "integer_extensions",
m: testcases.IntegerExtensions.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
sxtw x4?, w2?
uxtw x5?, w2?
sxtb x6?, w3?
sxth x7?, w3?
sxtw x8?, w3?
sxtb w9?, w2?
sxth w10?, w2?
mov x6, x10?
mov x5, x9?
mov x4, x8?
mov x3, x7?
mov x2, x6?
mov x1, x5?
mov x0, x4?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, x2
mov x9, x3
sxtw x0, w8
uxtw x1, w8
sxtb x2, w9
sxth x3, w9
sxtw x4, w9
sxtb w5, w8
sxth w6, w8
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "integer bit counts", m: testcases.IntegerBitCounts.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov x3?, x3
clz w4?, w2?
rbit w17?, w2?
clz w5?, w17?
ins v14?.d[0], x2?
cnt v15?.16b, v14?.16b
uaddlv h16?, v15?.8b
mov x6?, v16?.d[0]
clz x7?, x3?
rbit x13?, x3?
clz x8?, x13?
ins v10?.d[0], x3?
cnt v11?.16b, v10?.16b
uaddlv h12?, v11?.8b
mov x9?, v12?.d[0]
mov x5, x9?
mov x4, x8?
mov x3, x7?
mov x2, x6?
mov x1, x5?
mov x0, x4?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, x3
clz w0, w2
rbit w9, w2
clz w1, w9
ins v8.d[0], x2
cnt v8.16b, v8.16b
uaddlv h8, v8.8b
mov x2, v8.d[0]
clz x3, x8
rbit x9, x8
clz x4, x9
ins v8.d[0], x8
cnt v8.16b, v8.16b
uaddlv h8, v8.8b
mov x5, v8.d[0]
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "float_comparisons",
m: testcases.FloatComparisons.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
orr x27, xzr, #0x20
sub sp, sp, x27
stp x30, x27, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
fcmp s0, s1
cset x0, eq
fcmp s0, s1
cset x1, ne
fcmp s0, s1
cset x2, mi
fcmp s0, s1
cset x3, gt
fcmp s0, s1
cset x4, ls
fcmp s0, s1
cset x5, ge
fcmp d2, d3
cset x6, eq
fcmp d2, d3
cset x7, ne
fcmp d2, d3
cset x11, mi
fcmp d2, d3
cset x10, gt
fcmp d2, d3
cset x9, ls
fcmp d2, d3
cset x8, ge
str w8, [sp, #0x38]
str w9, [sp, #0x30]
str w10, [sp, #0x28]
str w11, [sp, #0x20]
add sp, sp, #0x10
ldr x30, [sp], #0x10
add sp, sp, #0x20
ret
`,
},
{
name: "float_conversions",
m: testcases.FloatConversions.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, x0
msr fpsr, xzr
fcvtzs x0, d0
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L17)
fcmp d0, d0
b.vc #0x34, (L16)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L16:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L17:
msr fpsr, xzr
fcvtzs x1, s1
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L15)
fcmp s1, s1
b.vc #0x34, (L14)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L14:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L15:
msr fpsr, xzr
fcvtzs w2, d0
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L13)
fcmp d0, d0
b.vc #0x34, (L12)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L12:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L13:
msr fpsr, xzr
fcvtzs w3, s1
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L11)
fcmp s1, s1
b.vc #0x34, (L10)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L10:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L11:
msr fpsr, xzr
fcvtzu x4, d0
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L9)
fcmp d0, d0
b.vc #0x34, (L8)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L8:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L9:
msr fpsr, xzr
fcvtzu x5, s1
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L7)
fcmp s1, s1
b.vc #0x34, (L6)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L6:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L7:
msr fpsr, xzr
fcvtzu w6, d0
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L5)
fcmp d0, d0
b.vc #0x34, (L4)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L4:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L5:
msr fpsr, xzr
fcvtzu w7, s1
mrs x9 fpsr
subs xzr, x9, #0x1
b.ne #0x6c, (L3)
fcmp s1, s1
b.vc #0x34, (L2)
movz x9, #0xc, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L2:
movz x9, #0xb, lsl 0
str w9, [x8]
mov x9, sp
str x9, [x8, #0x38]
adr x9, #0x0
str x9, [x8, #0x30]
exit_sequence x8
L3:
fcvt s0, d0
fcvt d1, s1
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "nontrapping_float_conversions",
m: testcases.NonTrappingFloatConversions.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
fcvtzs x0, d0
fcvtzs x1, s1
fcvtzs w2, d0
fcvtzs w3, s1
fcvtzu x4, d0
fcvtzu x5, s1
fcvtzu w6, d0
fcvtzu w7, s1
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "many_middle_values",
m: testcases.ManyMiddleValues.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
mov v3?.8b, v0.8b
orr w161?, wzr, #0x1
madd w5?, w2?, w161?, wzr
orr w160?, wzr, #0x2
madd w7?, w2?, w160?, wzr
orr w159?, wzr, #0x3
madd w9?, w2?, w159?, wzr
orr w158?, wzr, #0x4
madd w11?, w2?, w158?, wzr
movz w157?, #0x5, lsl 0
madd w13?, w2?, w157?, wzr
orr w156?, wzr, #0x6
madd w15?, w2?, w156?, wzr
orr w155?, wzr, #0x7
madd w17?, w2?, w155?, wzr
orr w154?, wzr, #0x8
madd w19?, w2?, w154?, wzr
movz w153?, #0x9, lsl 0
madd w21?, w2?, w153?, wzr
movz w152?, #0xa, lsl 0
madd w23?, w2?, w152?, wzr
movz w151?, #0xb, lsl 0
madd w25?, w2?, w151?, wzr
orr w150?, wzr, #0xc
madd w27?, w2?, w150?, wzr
movz w149?, #0xd, lsl 0
madd w29?, w2?, w149?, wzr
orr w148?, wzr, #0xe
madd w31?, w2?, w148?, wzr
orr w147?, wzr, #0xf
madd w33?, w2?, w147?, wzr
orr w146?, wzr, #0x10
madd w35?, w2?, w146?, wzr
movz w145?, #0x11, lsl 0
madd w37?, w2?, w145?, wzr
movz w144?, #0x12, lsl 0
madd w39?, w2?, w144?, wzr
movz w143?, #0x13, lsl 0
madd w41?, w2?, w143?, wzr
movz w142?, #0x14, lsl 0
madd w43?, w2?, w142?, wzr
add w44?, w41?, w43?
add w45?, w39?, w44?
add w46?, w37?, w45?
add w47?, w35?, w46?
add w48?, w33?, w47?
add w49?, w31?, w48?
add w50?, w29?, w49?
add w51?, w27?, w50?
add w52?, w25?, w51?
add w53?, w23?, w52?
add w54?, w21?, w53?
add w55?, w19?, w54?
add w56?, w17?, w55?
add w57?, w15?, w56?
add w58?, w13?, w57?
add w59?, w11?, w58?
add w60?, w9?, w59?
add w61?, w7?, w60?
add w62?, w5?, w61?
ldr s141?, #8; b 8; data.f32 1.000000
fmul s64?, s3?, s141?
ldr s140?, #8; b 8; data.f32 2.000000
fmul s66?, s3?, s140?
ldr s139?, #8; b 8; data.f32 3.000000
fmul s68?, s3?, s139?
ldr s138?, #8; b 8; data.f32 4.000000
fmul s70?, s3?, s138?
ldr s137?, #8; b 8; data.f32 5.000000
fmul s72?, s3?, s137?
ldr s136?, #8; b 8; data.f32 6.000000
fmul s74?, s3?, s136?
ldr s135?, #8; b 8; data.f32 7.000000
fmul s76?, s3?, s135?
ldr s134?, #8; b 8; data.f32 8.000000
fmul s78?, s3?, s134?
ldr s133?, #8; b 8; data.f32 9.000000
fmul s80?, s3?, s133?
ldr s132?, #8; b 8; data.f32 10.000000
fmul s82?, s3?, s132?
ldr s131?, #8; b 8; data.f32 11.000000
fmul s84?, s3?, s131?
ldr s130?, #8; b 8; data.f32 12.000000
fmul s86?, s3?, s130?
ldr s129?, #8; b 8; data.f32 13.000000
fmul s88?, s3?, s129?
ldr s128?, #8; b 8; data.f32 14.000000
fmul s90?, s3?, s128?
ldr s127?, #8; b 8; data.f32 15.000000
fmul s92?, s3?, s127?
ldr s126?, #8; b 8; data.f32 16.000000
fmul s94?, s3?, s126?
ldr s125?, #8; b 8; data.f32 17.000000
fmul s96?, s3?, s125?
ldr s124?, #8; b 8; data.f32 18.000000
fmul s98?, s3?, s124?
ldr s123?, #8; b 8; data.f32 19.000000
fmul s100?, s3?, s123?
ldr s122?, #8; b 8; data.f32 20.000000
fmul s102?, s3?, s122?
fadd s103?, s100?, s102?
fadd s104?, s98?, s103?
fadd s105?, s96?, s104?
fadd s106?, s94?, s105?
fadd s107?, s92?, s106?
fadd s108?, s90?, s107?
fadd s109?, s88?, s108?
fadd s110?, s86?, s109?
fadd s111?, s84?, s110?
fadd s112?, s82?, s111?
fadd s113?, s80?, s112?
fadd s114?, s78?, s113?
fadd s115?, s76?, s114?
fadd s116?, s74?, s115?
fadd s117?, s72?, s116?
fadd s118?, s70?, s117?
fadd s119?, s68?, s118?
fadd s120?, s66?, s119?
fadd s121?, s64?, s120?
mov v0.8b, v121?.8b
mov x0, x62?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str x19, [sp, #-0x10]!
str x20, [sp, #-0x10]!
str x21, [sp, #-0x10]!
str x22, [sp, #-0x10]!
str x23, [sp, #-0x10]!
str x24, [sp, #-0x10]!
str x25, [sp, #-0x10]!
str x26, [sp, #-0x10]!
str q18, [sp, #-0x10]!
str q19, [sp, #-0x10]!
str q20, [sp, #-0x10]!
str q21, [sp, #-0x10]!
str q22, [sp, #-0x10]!
str q23, [sp, #-0x10]!
str q24, [sp, #-0x10]!
str q25, [sp, #-0x10]!
str q26, [sp, #-0x10]!
str q27, [sp, #-0x10]!
movz x27, #0x120, lsl 0
str x27, [sp, #-0x10]!
orr w8, wzr, #0x1
madd w23, w2, w8, wzr
orr w8, wzr, #0x2
madd w22, w2, w8, wzr
orr w8, wzr, #0x3
madd w21, w2, w8, wzr
orr w8, wzr, #0x4
madd w20, w2, w8, wzr
movz w8, #0x5, lsl 0
madd w19, w2, w8, wzr
orr w8, wzr, #0x6
madd w17, w2, w8, wzr
orr w8, wzr, #0x7
madd w16, w2, w8, wzr
orr w8, wzr, #0x8
madd w15, w2, w8, wzr
movz w8, #0x9, lsl 0
madd w14, w2, w8, wzr
movz w8, #0xa, lsl 0
madd w13, w2, w8, wzr
movz w8, #0xb, lsl 0
madd w12, w2, w8, wzr
orr w8, wzr, #0xc
madd w11, w2, w8, wzr
movz w8, #0xd, lsl 0
madd w10, w2, w8, wzr
orr w8, wzr, #0xe
madd w9, w2, w8, wzr
orr w8, wzr, #0xf
madd w8, w2, w8, wzr
orr w24, wzr, #0x10
madd w24, w2, w24, wzr
movz w25, #0x11, lsl 0
madd w25, w2, w25, wzr
movz w26, #0x12, lsl 0
madd w26, w2, w26, wzr
movz w29, #0x13, lsl 0
madd w29, w2, w29, wzr
movz w30, #0x14, lsl 0
madd w30, w2, w30, wzr
add w29, w29, w30
add w26, w26, w29
add w25, w25, w26
add w24, w24, w25
add w8, w8, w24
add w8, w9, w8
add w8, w10, w8
add w8, w11, w8
add w8, w12, w8
add w8, w13, w8
add w8, w14, w8
add w8, w15, w8
add w8, w16, w8
add w8, w17, w8
add w8, w19, w8
add w8, w20, w8
add w8, w21, w8
add w8, w22, w8
add w0, w23, w8
ldr s8, #8; b 8; data.f32 1.000000
fmul s20, s0, s8
ldr s8, #8; b 8; data.f32 2.000000
fmul s19, s0, s8
ldr s8, #8; b 8; data.f32 3.000000
fmul s18, s0, s8
ldr s8, #8; b 8; data.f32 4.000000
fmul s17, s0, s8
ldr s8, #8; b 8; data.f32 5.000000
fmul s16, s0, s8
ldr s8, #8; b 8; data.f32 6.000000
fmul s15, s0, s8
ldr s8, #8; b 8; data.f32 7.000000
fmul s14, s0, s8
ldr s8, #8; b 8; data.f32 8.000000
fmul s13, s0, s8
ldr s8, #8; b 8; data.f32 9.000000
fmul s12, s0, s8
ldr s8, #8; b 8; data.f32 10.000000
fmul s11, s0, s8
ldr s8, #8; b 8; data.f32 11.000000
fmul s10, s0, s8
ldr s8, #8; b 8; data.f32 12.000000
fmul s9, s0, s8
ldr s8, #8; b 8; data.f32 13.000000
fmul s8, s0, s8
ldr s21, #8; b 8; data.f32 14.000000
fmul s21, s0, s21
ldr s22, #8; b 8; data.f32 15.000000
fmul s22, s0, s22
ldr s23, #8; b 8; data.f32 16.000000
fmul s23, s0, s23
ldr s24, #8; b 8; data.f32 17.000000
fmul s24, s0, s24
ldr s25, #8; b 8; data.f32 18.000000
fmul s25, s0, s25
ldr s26, #8; b 8; data.f32 19.000000
fmul s26, s0, s26
ldr s27, #8; b 8; data.f32 20.000000
fmul s27, s0, s27
fadd s26, s26, s27
fadd s25, s25, s26
fadd s24, s24, s25
fadd s23, s23, s24
fadd s22, s22, s23
fadd s21, s21, s22
fadd s8, s8, s21
fadd s8, s9, s8
fadd s8, s10, s8
fadd s8, s11, s8
fadd s8, s12, s8
fadd s8, s13, s8
fadd s8, s14, s8
fadd s8, s15, s8
fadd s8, s16, s8
fadd s8, s17, s8
fadd s8, s18, s8
fadd s8, s19, s8
fadd s0, s20, s8
add sp, sp, #0x10
ldr q27, [sp], #0x10
ldr q26, [sp], #0x10
ldr q25, [sp], #0x10
ldr q24, [sp], #0x10
ldr q23, [sp], #0x10
ldr q22, [sp], #0x10
ldr q21, [sp], #0x10
ldr q20, [sp], #0x10
ldr q19, [sp], #0x10
ldr q18, [sp], #0x10
ldr x26, [sp], #0x10
ldr x25, [sp], #0x10
ldr x24, [sp], #0x10
ldr x23, [sp], #0x10
ldr x22, [sp], #0x10
ldr x21, [sp], #0x10
ldr x20, [sp], #0x10
ldr x19, [sp], #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "imported_function_call", m: testcases.ImportedFunctionCall.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
mov x2?, x2
str x1?, [x0?, #0x8]
ldr x3?, [x1?, #0x8]
ldr x4?, [x1?, #0x10]
mov x0, x0?
mov x1, x4?
mov x2, x2?
mov x3, x2?
bl x3?
mov x5?, x0
mov x0, x5?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x3, x2
str x1, [x0, #0x8]
ldr x8, [x1, #0x8]
ldr x1, [x1, #0x10]
mov x2, x3
bl x8
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "memory_load_basic", m: testcases.MemoryLoadBasic.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
mov x2?, x2
uxtw x4?, w2?
ldr w5?, [x1?, #0x10]
add x6?, x4?, #0x4
subs xzr, x5?, x6?
b.hs L2
movz x12?, #0x4, lsl 0
str w12?, [x0?]
mov x13?, sp
str x13?, [x0?, #0x38]
adr x14?, #0x0
str x14?, [x0?, #0x30]
exit_sequence x0?
L2:
ldr x8?, [x1?, #0x8]
add x11?, x8?, x4?
ldr w10?, [x11?]
mov x0, x10?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
uxtw x8, w2
ldr w10, [x1, #0x10]
add x9, x8, #0x4
subs xzr, x10, x9
b.hs #0x34, (L2)
movz x9, #0x4, lsl 0
str w9, [x0]
mov x9, sp
str x9, [x0, #0x38]
adr x9, #0x0
str x9, [x0, #0x30]
exit_sequence x0
L2:
ldr x9, [x1, #0x8]
add x8, x9, x8
ldr w0, [x8]
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "memory_stores", m: testcases.MemoryStores.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov x8, xzr
uxtw x10, w8
ldr w8, [x1, #0x10]
add x9, x10, #0x4
subs xzr, x8, x9
b.hs #0x34, (L10)
movz x9, #0x4, lsl 0
str w9, [x0]
mov x9, sp
str x9, [x0, #0x38]
adr x9, #0x0
str x9, [x0, #0x30]
exit_sequence x0
L10:
ldr x9, [x1, #0x8]
add x10, x9, x10
str w2, [x10]
orr w10, wzr, #0x8
uxtw x10, w10
add x11, x10, #0x8
subs xzr, x8, x11
b.hs #0x34, (L9)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L9:
add x10, x9, x10
str x3, [x10]
orr w10, wzr, #0x10
uxtw x10, w10
add x11, x10, #0x4
subs xzr, x8, x11
b.hs #0x34, (L8)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L8:
add x10, x9, x10
str s0, [x10]
orr w10, wzr, #0x18
uxtw x10, w10
add x11, x10, #0x8
subs xzr, x8, x11
b.hs #0x34, (L7)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L7:
add x10, x9, x10
str d1, [x10]
orr w10, wzr, #0x20
uxtw x10, w10
add x11, x10, #0x1
subs xzr, x8, x11
b.hs #0x34, (L6)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L6:
add x10, x9, x10
strb w2, [x10]
movz w10, #0x28, lsl 0
uxtw x10, w10
add x11, x10, #0x2
subs xzr, x8, x11
b.hs #0x34, (L5)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L5:
add x10, x9, x10
strh w2, [x10]
orr w10, wzr, #0x30
uxtw x10, w10
add x11, x10, #0x1
subs xzr, x8, x11
b.hs #0x34, (L4)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L4:
add x10, x9, x10
strb w3, [x10]
orr w10, wzr, #0x38
uxtw x10, w10
add x11, x10, #0x2
subs xzr, x8, x11
b.hs #0x34, (L3)
movz x11, #0x4, lsl 0
str w11, [x0]
mov x11, sp
str x11, [x0, #0x38]
adr x11, #0x0
str x11, [x0, #0x30]
exit_sequence x0
L3:
add x10, x9, x10
strh w3, [x10]
orr w10, wzr, #0x40
uxtw x10, w10
add x11, x10, #0x4
subs xzr, x8, x11
b.hs #0x34, (L2)
movz x8, #0x4, lsl 0
str w8, [x0]
mov x8, sp
str x8, [x0, #0x38]
adr x8, #0x0
str x8, [x0, #0x30]
exit_sequence x0
L2:
add x8, x9, x10
str w3, [x8]
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "globals_mutable[0]",
m: testcases.GlobalsMutable.Module,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x0?, x0
mov x1?, x1
ldr x2?, [x1?, #0x8]
ldr w3?, [x2?, #0x8]
ldr x4?, [x1?, #0x10]
ldr x5?, [x4?, #0x8]
ldr x6?, [x1?, #0x18]
ldr s7?, [x6?, #0x8]
ldr x8?, [x1?, #0x20]
ldr d9?, [x8?, #0x8]
str x1?, [x0?, #0x8]
mov x0, x0?
mov x1, x1?
bl f1
ldr x10?, [x1?, #0x8]
ldr w11?, [x10?, #0x8]
ldr x12?, [x1?, #0x10]
ldr x13?, [x12?, #0x8]
ldr x14?, [x1?, #0x18]
ldr s15?, [x14?, #0x8]
ldr x16?, [x1?, #0x20]
ldr d17?, [x16?, #0x8]
mov v3.8b, v17?.8b
mov v2.8b, v15?.8b
mov x3, x13?
mov x2, x11?
mov v1.8b, v9?.8b
mov v0.8b, v7?.8b
mov x1, x5?
mov x0, x3?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
sub sp, sp, #0x20
orr x27, xzr, #0x20
str x27, [sp, #-0x10]!
mov x10, x1
ldr x8, [x10, #0x8]
ldr w8, [x8, #0x8]
ldr x9, [x10, #0x10]
ldr x9, [x9, #0x8]
ldr x11, [x10, #0x18]
ldr s0, [x11, #0x8]
ldr x11, [x10, #0x20]
ldr d1, [x11, #0x8]
str x10, [x0, #0x8]
mov x1, x10
str x10, [sp, #0x10]
str w8, [sp, #0x18]
str x9, [sp, #0x1c]
str s0, [sp, #0x24]
str d1, [sp, #0x28]
bl f1
ldr d1, [sp, #0x28]
ldr s0, [sp, #0x24]
ldr x9, [sp, #0x1c]
ldr w8, [sp, #0x18]
ldr x10, [sp, #0x10]
ldr x11, [x10, #0x8]
ldr w2, [x11, #0x8]
ldr x11, [x10, #0x10]
ldr x3, [x11, #0x8]
ldr x11, [x10, #0x18]
ldr s2, [x11, #0x8]
ldr x10, [x10, #0x20]
ldr d3, [x10, #0x8]
mov x1, x9
mov x0, x8
add sp, sp, #0x10
add sp, sp, #0x20
ldr x30, [sp], #0x10
ret
`,
},
{
name: "globals_mutable[1]",
m: testcases.GlobalsMutable.Module,
targetIndex: 1,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x1?, x1
ldr x3?, [x1?, #0x8]
orr w13?, wzr, #0x1
str w13?, [x3?, #0x8]
ldr x5?, [x1?, #0x10]
orr x12?, xzr, #0x2
str x12?, [x5?, #0x8]
ldr x7?, [x1?, #0x18]
ldr s11?, #8; b 8; data.f32 3.000000
str s11?, [x7?, #0x8]
ldr x9?, [x1?, #0x20]
ldr d10?, #8; b 16; data.f64 4.000000
str d10?, [x9?, #0x8]
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
ldr x9, [x1, #0x8]
orr w8, wzr, #0x1
str w8, [x9, #0x8]
ldr x9, [x1, #0x10]
orr x8, xzr, #0x2
str x8, [x9, #0x8]
ldr x8, [x1, #0x18]
ldr s8, #8; b 8; data.f32 3.000000
str s8, [x8, #0x8]
ldr x8, [x1, #0x20]
ldr d8, #8; b 16; data.f64 4.000000
str d8, [x8, #0x8]
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "br_table",
m: testcases.BrTable.Module,
targetIndex: 0,
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x2?, x2
orr w9?, wzr, #0x6
subs wzr, w2?, w9?
csel w10?, w9?, w2?, hs
br_table_sequence x10?, [L2, L3, L4, L5, L6, L7, L8]
L2 (SSA Block: blk7):
b L9
L3 (SSA Block: blk8):
L10 (SSA Block: blk5):
orr w3?, wzr, #0xc
mov x0, x3?
ret
L4 (SSA Block: blk9):
L11 (SSA Block: blk4):
movz w4?, #0xd, lsl 0
mov x0, x4?
ret
L5 (SSA Block: blk10):
L12 (SSA Block: blk3):
orr w5?, wzr, #0xe
mov x0, x5?
ret
L6 (SSA Block: blk11):
L13 (SSA Block: blk2):
orr w6?, wzr, #0xf
mov x0, x6?
ret
L7 (SSA Block: blk12):
L14 (SSA Block: blk1):
orr w7?, wzr, #0x10
mov x0, x7?
ret
L8 (SSA Block: blk13):
L9 (SSA Block: blk6):
movz w8?, #0xb, lsl 0
mov x0, x8?
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
orr w8, wzr, #0x6
subs wzr, w2, w8
csel w8, w8, w2, hs
adr x27, #16; ldrsw x8, [x27, x8, UXTW 2]; add x27, x27, x8; br x27; [0x1c 0x20 0x30 0x40 0x50 0x60 0x70]
L2 (SSA Block: blk7):
b #0x54 (L9)
L3 (SSA Block: blk8):
L10 (SSA Block: blk5):
orr w0, wzr, #0xc
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L4 (SSA Block: blk9):
L11 (SSA Block: blk4):
movz w0, #0xd, lsl 0
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L5 (SSA Block: blk10):
L12 (SSA Block: blk3):
orr w0, wzr, #0xe
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L6 (SSA Block: blk11):
L13 (SSA Block: blk2):
orr w0, wzr, #0xf
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L7 (SSA Block: blk12):
L14 (SSA Block: blk1):
orr w0, wzr, #0x10
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
L8 (SSA Block: blk13):
L9 (SSA Block: blk6):
movz w0, #0xb, lsl 0
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
{
name: "VecShuffle",
m: testcases.VecShuffle.Module,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
mov v29.16b, v0.16b
mov v30.16b, v1.16b
ldr q8, #8; b 32; data.v128 0706050403020100 1f1e1d1c1b1a1918
tbl v0.16b, { v29.16b, v30.16b }, v8.16b
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
`,
},
} {
t.Run(tc.name, func(t *testing.T) {
ssab := ssa.NewBuilder()
offset := wazevoapi.NewModuleContextOffsetData(tc.m, false)
fc := frontend.NewFrontendCompiler(tc.m, ssab, &offset, false, false, false)
machine := newMachine()
machine.DisableStackCheck()
be := backend.NewCompiler(context.Background(), machine, ssab)
// Lowers the Wasm to SSA.
typeIndex := tc.m.FunctionSection[tc.targetIndex]
code := &tc.m.CodeSection[tc.targetIndex]
fc.Init(tc.targetIndex, typeIndex, &tc.m.TypeSection[typeIndex], code.LocalTypes, code.Body, false, 0)
fc.LowerToSSA()
if verbose {
fmt.Println("============ SSA before passes ============")
fmt.Println(ssab.Format())
}
// Need to run passes before lowering to machine code.
ssab.RunPasses()
if verbose {
fmt.Println("============ SSA after passes ============")
fmt.Println(ssab.Format())
}
ssab.LayoutBlocks()
if verbose {
fmt.Println("============ SSA after block layout ============")
fmt.Println(ssab.Format())
}
// Lowers the SSA to ISA specific code.
be.Lower()
if verbose {
fmt.Println("============ lowering result ============")
fmt.Println(be.Format())
}
switch runtime.GOARCH {
case "arm64":
if tc.afterLoweringARM64 != "" {
require.Equal(t, tc.afterLoweringARM64, be.Format())
}
default:
t.Fail()
}
be.RegAlloc()
if verbose {
fmt.Println("============ regalloc result ============")
fmt.Println(be.Format())
}
be.Finalize()
if verbose {
fmt.Println("============ finalization result ============")
fmt.Println(be.Format())
}
switch runtime.GOARCH {
case "arm64":
require.Equal(t, tc.afterFinalizeARM64, be.Format())
default:
t.Fail()
}
// Sanity check on the final binary encoding.
be.Encode()
})
}
}