summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/binop-x64-ion-folding.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/binop-x64-ion-folding.js')
-rw-r--r--js/src/jit-test/tests/wasm/binop-x64-ion-folding.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/binop-x64-ion-folding.js b/js/src/jit-test/tests/wasm/binop-x64-ion-folding.js
new file mode 100644
index 0000000000..b291077d17
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/binop-x64-ion-folding.js
@@ -0,0 +1,212 @@
+// |jit-test| skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || !getBuildConfiguration("x64") || getBuildConfiguration("simulator"); include:codegen-x64-test.js
+
+// This file checks folding rules for wasm {and,or,xor}{32,64} on x64 via Ion.
+// See also binop-x64-ion-codegen.js, which is similar.
+
+// These tests check that a folding has happened. The function is also run
+// and the result value checked. Note, many of the functions ignore one or
+// both of their parameters.
+//
+// In many cases the expected code contains an unnecessary move via a
+// temporary, generally e/rcx, for example:
+//
+// mov %rdi, %rcx
+// mov %rcx, %rax
+//
+// where rdi is the first arg reg (on Linux) and rax is the retval reg. This
+// is documented in bug 1701164. If/when that gets fixed, we will presumably
+// have to redo the expected-outputs here.
+//
+// The situation is complicated further because many of the expected outputs
+// here depend on one of the two argument registers, but they are different in
+// the ELF ABI (rdi, rsi) and the Win64 ABI (rcx, rdx). For the latter case,
+// the abovementioned spurious move from the first arg reg into rcx
+// disappears. Hence there is some fudging using wildcards in register names,
+// and `no_prefix`, to make the tests pass with both ABIs.
+
+function test(ty, wasm_insn, must_appear, param0, param1, expected_result,
+ options = {}) {
+ let t =
+ `(module
+ (func (export "f") (param ${ty}) (param ${ty}) (result ${ty})
+ ${wasm_insn}
+ ))`;
+ options.instanceBox = {value: null};
+ codegenTestX64_adhoc(t, "f", must_appear, options);
+ let ins = options.instanceBox.value;
+ assertEq(ins.exports.f(param0, param1), expected_result);
+}
+
+function test32(wasm_insn, must_appear, param0, param1, expected_result,
+ options) {
+ return test('i32', wasm_insn, must_appear, param0, param1, expected_result,
+ options);
+}
+
+function test64(wasm_insn, must_appear, param0, param1, expected_result,
+ options) {
+ return test('i64', wasm_insn, must_appear, param0, param1, expected_result,
+ options);
+}
+
+// {AND,OR,XOR}{32,64} folding: both args const
+
+test32('(i32.and (i32.const 0x12345678) (i32.const 0x0f0f0f0f))',
+ 'b8 08 06 04 02 mov \\$0x2040608, %eax',
+ 0,0, 0x2040608);
+test64('(i64.and (i64.const 0x1234567851505150) (i64.const 0x515051500f0f0f0f))',
+ '48 b8 00 01 00 01 50 50 10 10 mov \\$0x1010505001000100, %rax',
+ 0n,0n, 0x1010505001000100n);
+
+test32('(i32.or (i32.const 0x12345678) (i32.const 0x0f0e0d0c))',
+ 'b8 7c 5f 3e 1f mov \\$0x1F3E5F7C, %eax',
+ 0,0, 0x1f3e5f7c);
+test64('(i64.or (i64.const 0x1234567851505150) (i64.const 0x515051500f0f1337))',
+ '48 b8 77 53 5f 5f 78 57 74 53 mov \\$0x537457785F5F5377, %rax',
+ 0n,0n, 0x537457785f5f5377n);
+
+test32('(i32.xor (i32.const 0x12345678) (i32.const 0x0f0e0d0c))',
+ 'b8 74 5b 3a 1d mov \\$0x1D3A5B74, %eax',
+ 0,0, 0x1d3a5b74);
+test64('(i64.xor (i64.const 0x1234567851505150) (i64.const 0x515051500f0f1337))',
+ '48 b8 67 42 5f 5e 28 07 64 43 mov \\$0x436407285E5F4267, %rax',
+ 0n,0n, 0x436407285e5f4267n);
+
+// {AND,OR,XOR}{32,64} identities: first arg is all zeroes
+
+test32('(i32.and (i32.const 0) (local.get 1))',
+ '33 c0 xor %eax, %eax',
+ 1234,5678, 0);
+test64('(i64.and (i64.const 0) (local.get 1))',
+ '33 c0 xor %eax, %eax',
+ 1234n,5678n, 0n);
+
+test32('(i32.or (i32.const 0) (local.get 1))',
+ `8b .. mov %e.., %ecx
+ 8b c1 mov %ecx, %eax`,
+ 1234,5678, 5678);
+test64('(i64.or (i64.const 0) (local.get 1))',
+ `48 89 .. mov %r.., %rcx
+ 48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 5678n);
+
+test32('(i32.xor (i32.const 0) (local.get 1))',
+ `8b .. mov %e.., %ecx
+ 8b c1 mov %ecx, %eax`,
+ 1234,5678, 5678);
+test64('(i64.xor (i64.const 0) (local.get 1))',
+ `48 89 .. mov %r.., %rcx
+ 48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 5678n);
+
+// {AND,OR,XOR}{32,64} identities: second arg is all zeroes
+
+test32('(i32.and (local.get 0) (i32.const 0))',
+ '33 c0 xor %eax, %eax',
+ 1234,5678, 0);
+test64('(i64.and (local.get 0) (i64.const 0))',
+ '33 c0 xor %eax, %eax',
+ 1234n,5678n, 0n);
+
+test32('(i32.or (local.get 0) (i32.const 0))',
+ // 8b cf mov %edi, %ecx -- expected on Linux but not on Windows
+ `8b c1 mov %ecx, %eax`,
+ 1234,5678, 1234, {no_prefix: true}); // required on Linux
+test64('(i64.or (local.get 0) (i64.const 0))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 1234n, {no_prefix: true});
+
+test32('(i32.xor (local.get 0) (i32.const 0))',
+ // 8b cf mov %edi, %ecx -- ditto
+ `8b c1 mov %ecx, %eax`,
+ 1234,5678, 1234, {no_prefix: true});
+test64('(i64.xor (local.get 0) (i64.const 0))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 1234n, {no_prefix: true});
+
+// {AND,OR,XOR}{32,64} identities: first arg is all ones
+
+test32('(i32.and (i32.const 0xffffffff) (local.get 1))',
+ `8b .. mov %e.., %ecx
+ 8b c1 mov %ecx, %eax`,
+ 1234,5678, 5678);
+test64('(i64.and (i64.const 0xffffffffffffffff) (local.get 1))',
+ `48 89 .. mov %r.., %rcx
+ 48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 5678n);
+
+test32('(i32.or (i32.const 0xffffffff) (local.get 1))',
+ 'b8 ff ff ff ff mov \\$-0x01, %eax',
+ 1234,5678, -1/*0xffffffff*/);
+test64('(i64.or (i64.const 0xffffffffffffffff) (local.get 1))',
+ '48 c7 c0 ff ff ff ff mov \\$-0x01, %rax',
+ 1234n,5678n, -1n/*0xffffffffffffffff*/);
+
+test32('(i32.xor (i32.const 0xffffffff) (local.get 1))',
+ `8b .. mov %e.., %ecx
+ 8b c1 mov %ecx, %eax
+ f7 d0 not %eax`,
+ 1234,5678, -5679);
+test64('(i64.xor (i64.const 0xffffffffffffffff) (local.get 1))',
+ `48 89 .. mov %r.., %rcx
+ 48 89 c8 mov %rcx, %rax
+ 48 f7 d0 not %rax`,
+ 1234n,5678n, -5679n);
+
+// {AND,OR,XOR}{32,64} identities: second arg is all ones
+
+test32('(i32.and (local.get 0) (i32.const 0xffffffff))',
+ // 8b cf mov %edi, %ecx -- expected on Linux but not on Windows
+ `8b c1 mov %ecx, %eax`,
+ 1234,5678, 1234, {no_prefix: true}); // required on Linux
+test64('(i64.and (local.get 0) (i64.const 0xffffffffffffffff))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 1234n, {no_prefix: true});
+
+test32('(i32.or (local.get 0) (i32.const 0xffffffff))',
+ 'b8 ff ff ff ff mov \\$-0x01, %eax',
+ 1234,5678, -1/*0xffffffff*/);
+test64('(i64.or (local.get 0) (i64.const 0xffffffffffffffff))',
+ '48 c7 c0 ff ff ff ff mov \\$-0x01, %rax',
+ 1234n,5678n, -1n/*0xffffffffffffffff*/);
+
+test32('(i32.xor (local.get 0) (i32.const 0xffffffff))',
+ // 8b cf mov %edi, %ecx -- ditto
+ `8b c1 mov %ecx, %eax
+ f7 d0 not %eax`,
+ 1234,5678, -1235, {no_prefix: true});
+test64('(i64.xor (local.get 0) (i64.const 0xffffffffffffffff))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax
+ 48 f7 d0 not %rax`,
+ 1234n,5678n, -1235n, {no_prefix: true});
+
+// {AND,OR,XOR}{32,64} identities: both args the same
+
+test32('(i32.and (local.get 0) (local.get 0))',
+ // 8b cf mov %edi, %ecx -- ditto
+ `8b c1 mov %ecx, %eax`,
+ 1234,5678, 1234, {no_prefix: true});
+test64('(i64.and (local.get 0) (local.get 0))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 1234n, {no_prefix: true});
+
+test32('(i32.or (local.get 0) (local.get 0))',
+ // 8b cf mov %edi, %ecx -- ditto
+ `8b c1 mov %ecx, %eax`,
+ 1234,5678, 1234, {no_prefix: true});
+test64('(i64.or (local.get 0) (local.get 0))',
+ // 48 89 f9 mov %rdi, %rcx -- ditto
+ `48 89 c8 mov %rcx, %rax`,
+ 1234n,5678n, 1234n, {no_prefix: true});
+
+test32('(i32.xor (local.get 0) (local.get 0))',
+ '33 c0 xor %eax, %eax',
+ 1234,5678, 0);
+test64('(i64.xor (local.get 0) (local.get 0))',
+ '33 c0 xor %eax, %eax',
+ 1234n,5678n, 0n);