const-arm64-vixl-codegen.js (3298B)
1 // |jit-test| skip-if: !wasmSimdEnabled() || !hasDisassembler() || wasmCompileMode() != "baseline" || !getBuildConfiguration("arm64") 2 3 // Test that the vixl logic for v128 constant loads is at least somewhat 4 // reasonable. 5 6 var lead = `0x[0-9a-f]+ +[0-9a-f]{8} +`; 7 8 var prefix = `${lead}sub sp, sp, #0x.. \\(..\\) 9 ${lead}str x23, \\[sp, #..\\]`; 10 11 var suffix = 12 `${lead}b #\\+0x18 \\(addr 0x.*\\) 13 ${lead}brk #0xf000`; 14 15 for ( let [bits, expected, values] of [ 16 // If high == low and the byte is 0 or ff then a single movi is sufficient. 17 ['i8x16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00', ` 18 ${prefix} 19 ${lead}movi v0\\.2d, #0x0 20 ${suffix} 21 `, 22 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 23 24 ['i8x16 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0', ` 25 ${prefix} 26 ${lead}movi v0\\.2d, #0xff00ff00ff00ff 27 ${suffix} 28 `, 29 [-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0]], 30 31 // Splattable small things (up to a byte, at a byte location) 32 // can also use just one instruction 33 ['i32x4 1 1 1 1', ` 34 ${prefix} 35 ${lead}movi v0\\.4s, #0x1, lsl #0 36 ${suffix} 37 `, 38 [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]], 39 40 ['i32x4 0x300 0x300 0x300 0x300', ` 41 ${prefix} 42 ${lead}movi v0\\.4s, #0x3, lsl #8 43 ${suffix} 44 `, 45 [0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0]], 46 47 // If high == low but the value is more complex then a constant load 48 // plus a dup is sufficient. x16 is the designated temp. 49 ['i32x4 1 2 1 2', ` 50 ${prefix} 51 ${lead}mov x16, #0x1 52 ${lead}movk x16, #0x2, lsl #32 53 ${lead}dup v0\\.2d, x16 54 ${suffix} 55 `, 56 [1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0]], 57 58 // If high != low then we degenerate to a more complicated pattern: dup the low value 59 // and then overwrite the high part with the high value. 60 ['i32x4 1 2 2 1', ` 61 ${prefix} 62 ${lead}mov x16, #0x1 63 ${lead}movk x16, #0x2, lsl #32 64 ${lead}dup v0\\.2d, x16 65 ${lead}mov x16, #0x2 66 ${lead}movk x16, #0x1, lsl #32 67 ${lead}mov v0\\.d\\[1\\], x16 68 ${suffix} 69 `, 70 [1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0]], 71 72 // Things are not always bleak, and vixl finds a way. 73 ['i32x4 1 1 2 2', ` 74 ${prefix} 75 ${lead}movi v0\\.4s, #0x1, lsl #0 76 ${lead}mov x16, #0x200000002 77 ${lead}mov v0\\.d\\[1\\], x16 78 ${suffix} 79 `, 80 [1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0]], 81 ] ) { 82 let ins = wasmEvalText(` 83 (module 84 (memory (export "mem") 1) 85 (func (export "run") 86 (v128.store (i32.const 0) (call $f))) 87 (func $f (export "f") (result v128) 88 (v128.const ${bits})))`); 89 let output = wasmDis(ins.exports.f, {tier:"baseline", asString:true}); 90 let pass = output.match(new RegExp(expected)) != null; 91 if (!pass) { 92 // Debugging output in case of failure. 93 console.log("expected:\n", expected, 94 "\n\noutput:\n", output); 95 } 96 assertEq(pass, true); 97 let mem = new Int8Array(ins.exports.mem.buffer); 98 set(mem, 0, iota(16).map(x => -1-x)); 99 ins.exports.run(); 100 assertSame(get(mem, 0, 16), values); 101 } 102 103 function get(arr, loc, len) { 104 let res = []; 105 for ( let i=0; i < len; i++ ) { 106 res.push(arr[loc+i]); 107 } 108 return res; 109 } 110 111 function set(arr, loc, vals) { 112 for ( let i=0; i < vals.length; i++ ) { 113 arr[loc+i] = vals[i]; 114 } 115 }