tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

binop-x64-ion-folding.js (7549B)


      1 // |jit-test| skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || !getBuildConfiguration("x64") || getBuildConfiguration("simulator"); include:codegen-x64-test.js
      2 
      3 // This file checks folding rules for wasm {and,or,xor}{32,64} on x64 via Ion.
      4 // See also binop-x64-ion-codegen.js, which is similar.
      5 
      6 // These tests check that a folding has happened.  The function is also run
      7 // and the result value checked.  Note, many of the functions ignore one or
      8 // both of their parameters.
      9 //
     10 // In many cases the expected code contains an unnecessary move via a
     11 // temporary, generally e/rcx, for example:
     12 //
     13 //   mov %rdi, %rcx
     14 //   mov %rcx, %rax
     15 //
     16 // where rdi is the first arg reg (on Linux) and rax is the retval reg.  This
     17 // is documented in bug 1701164.  If/when that gets fixed, we will presumably
     18 // have to redo the expected-outputs here.
     19 //
     20 // The situation is complicated further because many of the expected outputs
     21 // here depend on one of the two argument registers, but they are different in
     22 // the ELF ABI (rdi, rsi) and the Win64 ABI (rcx, rdx).  For the latter case,
     23 // the abovementioned spurious move from the first arg reg into rcx
     24 // disappears.  Hence there is some fudging using wildcards in register names,
     25 // and `no_prefix`, to make the tests pass with both ABIs.
     26 
     27 function test(ty, wasm_insn, must_appear, param0, param1, expected_result,
     28              options = {}) {
     29    let t =
     30        `(module
     31           (func (export "f") (param ${ty}) (param ${ty}) (result ${ty})
     32             ${wasm_insn}
     33        ))`;
     34    options.instanceBox = {value: null};
     35    codegenTestX64_adhoc(t, "f", must_appear, options);
     36    let ins = options.instanceBox.value;
     37    assertEq(ins.exports.f(param0, param1), expected_result);
     38 }
     39 
     40 function test32(wasm_insn, must_appear, param0, param1, expected_result,
     41                options) {
     42    return test('i32', wasm_insn, must_appear, param0, param1, expected_result,
     43                options);
     44 }
     45 
     46 function test64(wasm_insn, must_appear, param0, param1, expected_result,
     47                options) {
     48    return test('i64', wasm_insn, must_appear, param0, param1, expected_result,
     49               options);
     50 }
     51 
     52 // {AND,OR,XOR}{32,64} folding: both args const
     53 
     54 test32('(i32.and (i32.const 0x12345678) (i32.const 0x0f0f0f0f))',
     55       'mov \\$0x2040608, %eax',
     56       0,0, 0x2040608);
     57 test64('(i64.and (i64.const 0x1234567851505150) (i64.const 0x515051500f0f0f0f))',
     58       'mov \\$0x1010505001000100, %rax',
     59       0n,0n, 0x1010505001000100n);
     60 
     61 test32('(i32.or (i32.const 0x12345678) (i32.const 0x0f0e0d0c))',
     62       'mov \\$0x1F3E5F7C, %eax',
     63       0,0, 0x1f3e5f7c);
     64 test64('(i64.or (i64.const 0x1234567851505150) (i64.const 0x515051500f0f1337))',
     65       'mov \\$0x537457785F5F5377, %rax',
     66       0n,0n, 0x537457785f5f5377n);
     67 
     68 test32('(i32.xor (i32.const 0x12345678) (i32.const 0x0f0e0d0c))',
     69       'mov \\$0x1D3A5B74, %eax',
     70       0,0, 0x1d3a5b74);
     71 test64('(i64.xor (i64.const 0x1234567851505150) (i64.const 0x515051500f0f1337))',
     72       'mov \\$0x436407285E5F4267, %rax',
     73       0n,0n, 0x436407285e5f4267n);
     74 
     75 // {AND,OR,XOR}{32,64} identities: first arg is all zeroes
     76 
     77 test32('(i32.and (i32.const 0) (local.get 1))',
     78       'xor %eax, %eax',
     79       1234,5678, 0);
     80 test64('(i64.and (i64.const 0) (local.get 1))',
     81       'xor %eax, %eax',
     82       1234n,5678n, 0n);
     83 
     84 test32('(i32.or (i32.const 0) (local.get 1))',
     85       `mov %e.., %ecx
     86        mov %ecx, %eax`,
     87       1234,5678, 5678);
     88 test64('(i64.or (i64.const 0) (local.get 1))',
     89       `mov %r.., %rcx
     90        mov %rcx, %rax`,
     91       1234n,5678n, 5678n);
     92 
     93 test32('(i32.xor (i32.const 0) (local.get 1))',
     94       `mov %e.., %ecx
     95        mov %ecx, %eax`,
     96       1234,5678, 5678);
     97 test64('(i64.xor (i64.const 0) (local.get 1))',
     98       `mov %r.., %rcx
     99        mov %rcx, %rax`,
    100       1234n,5678n, 5678n);
    101 
    102 // {AND,OR,XOR}{32,64} identities: second arg is all zeroes
    103 
    104 test32('(i32.and (local.get 0) (i32.const 0))',
    105       'xor %eax, %eax',
    106       1234,5678, 0);
    107 test64('(i64.and (local.get 0) (i64.const 0))',
    108       'xor %eax, %eax',
    109       1234n,5678n, 0n);
    110 
    111 test32('(i32.or (local.get 0) (i32.const 0))',
    112     // mov %edi, %ecx  -- expected on Linux but not on Windows
    113       `mov %ecx, %eax`,
    114       1234,5678, 1234, {no_prefix: true}); // required on Linux
    115 test64('(i64.or (local.get 0) (i64.const 0))',
    116     // mov %rdi, %rcx  -- ditto
    117       `mov %rcx, %rax`,
    118       1234n,5678n, 1234n, {no_prefix: true});
    119 
    120 test32('(i32.xor (local.get 0) (i32.const 0))',
    121     // mov %edi, %ecx  -- ditto
    122       `mov %ecx, %eax`,
    123       1234,5678, 1234, {no_prefix: true});
    124 test64('(i64.xor (local.get 0) (i64.const 0))',
    125     // mov %rdi, %rcx  -- ditto
    126       `mov %rcx, %rax`,
    127       1234n,5678n, 1234n, {no_prefix: true});
    128 
    129 // {AND,OR,XOR}{32,64} identities: first arg is all ones
    130 
    131 test32('(i32.and (i32.const 0xffffffff) (local.get 1))',
    132       `mov %e.., %ecx
    133        mov %ecx, %eax`,
    134       1234,5678, 5678);
    135 test64('(i64.and (i64.const 0xffffffffffffffff) (local.get 1))',
    136       `mov %r.., %rcx
    137        mov %rcx, %rax`,
    138       1234n,5678n, 5678n);
    139 
    140 test32('(i32.or (i32.const 0xffffffff) (local.get 1))',
    141       'mov \\$-0x01, %eax',
    142       1234,5678, -1/*0xffffffff*/);
    143 test64('(i64.or (i64.const 0xffffffffffffffff) (local.get 1))',
    144       'mov \\$-0x01, %rax',
    145       1234n,5678n, -1n/*0xffffffffffffffff*/);
    146 
    147 test32('(i32.xor (i32.const 0xffffffff) (local.get 1))',
    148       `mov %e.., %ecx
    149        mov %ecx, %eax
    150        not %eax`,
    151       1234,5678, -5679);
    152 test64('(i64.xor (i64.const 0xffffffffffffffff) (local.get 1))',
    153       `mov %r.., %rcx
    154        mov %rcx, %rax
    155        not %rax`,
    156       1234n,5678n, -5679n);
    157 
    158 // {AND,OR,XOR}{32,64} identities: second arg is all ones
    159 
    160 test32('(i32.and (local.get 0) (i32.const 0xffffffff))',
    161     // mov %edi, %ecx  -- expected on Linux but not on Windows
    162       `mov %ecx, %eax`,
    163       1234,5678, 1234, {no_prefix: true}); // required on Linux
    164 test64('(i64.and (local.get 0) (i64.const 0xffffffffffffffff))',
    165     // mov %rdi, %rcx  -- ditto
    166       `mov %rcx, %rax`,
    167       1234n,5678n, 1234n, {no_prefix: true});
    168 
    169 test32('(i32.or (local.get 0) (i32.const 0xffffffff))',
    170       'mov \\$-0x01, %eax',
    171       1234,5678, -1/*0xffffffff*/);
    172 test64('(i64.or (local.get 0) (i64.const 0xffffffffffffffff))',
    173       'mov \\$-0x01, %rax',
    174       1234n,5678n, -1n/*0xffffffffffffffff*/);
    175 
    176 test32('(i32.xor (local.get 0) (i32.const 0xffffffff))',
    177     // mov %edi, %ecx  -- ditto
    178       `mov %ecx, %eax
    179        not %eax`,
    180       1234,5678, -1235, {no_prefix: true});
    181 test64('(i64.xor (local.get 0) (i64.const 0xffffffffffffffff))',
    182     // mov %rdi, %rcx  -- ditto
    183       `mov %rcx, %rax
    184        not %rax`,
    185       1234n,5678n, -1235n, {no_prefix: true});
    186 
    187 // {AND,OR,XOR}{32,64} identities: both args the same
    188 
    189 test32('(i32.and (local.get 0) (local.get 0))',
    190     // mov %edi, %ecx  -- ditto
    191       `mov %ecx, %eax`,
    192       1234,5678, 1234, {no_prefix: true});
    193 test64('(i64.and (local.get 0) (local.get 0))',
    194     // mov %rdi, %rcx  -- ditto
    195       `mov %rcx, %rax`,
    196       1234n,5678n, 1234n, {no_prefix: true});
    197 
    198 test32('(i32.or (local.get 0) (local.get 0))',
    199     // mov %edi, %ecx  -- ditto
    200       `mov %ecx, %eax`,
    201       1234,5678, 1234, {no_prefix: true});
    202 test64('(i64.or (local.get 0) (local.get 0))',
    203     // mov %rdi, %rcx  -- ditto
    204       `mov %rcx, %rax`,
    205       1234n,5678n, 1234n, {no_prefix: true});
    206 
    207 test32('(i32.xor (local.get 0) (local.get 0))',
    208       'xor %eax, %eax',
    209       1234,5678, 0);
    210 test64('(i64.xor (local.get 0) (local.get 0))',
    211       'xor %eax, %eax',
    212       1234n,5678n, 0n);