summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/baseline-opt.js
blob: 87df25c245d02a1616032e8966ca458f26a944a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Point-testing various optimizations in the wasm baseline compiler.

// Boolean optimization for control (bug 1286816).
//
// These optimizations combine a test (a comparison or Eqz) with an
// immediately following conditional branch (BrIf, If, and Select), to
// avoid generating a boolean value that is then tested with a
// compare-to-zero.
//
// On AngryBots as of November 2016, 84% of all test instructions
// (measured statically) are optimized by this method.

function testEqzBrIf(value, type, untaken, taken, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (local i32)
			    (local.set 0 (${type}.const ${value}))
			    (local.set 1 (i32.const ${taken}))
			    (block $b
			     (br_if $b (${type}.eqz (local.get 0)))
			     (local.set 1 (i32.const ${untaken})))
			    (local.get 1))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64"].forEach(t => testEqzBrIf(0, t, 37, 42, 42)); // Taken
["i32", "i64"].forEach(t => testEqzBrIf(1, t, 37, 42, 37)); // Untaken

function testCmpBrIf(value, type, untaken, taken, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (local i32)
			    (local.set 1 (i32.const ${taken}))
			    (block $b
			     (br_if $b (${type}.eq (local.get 0) (${type}.const ${value})))
			     (local.set 1 (i32.const ${untaken})))
			    (local.get 1))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64", "f32", "f64"].forEach(t => testCmpBrIf(0, t, 37, 42, 42)); // Branch taken
["i32", "i64", "f32", "f64"].forEach(t => testCmpBrIf(1, t, 37, 42, 37)); // Branch untaken

function testEqzSelect(value, type, iftrue, iffalse, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (local.set 0 (${type}.const ${value}))
			    (select (i32.const ${iftrue})
			            (i32.const ${iffalse})
			            (${type}.eqz (local.get 0))))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64"].forEach(t => testEqzSelect(0, t, 42, 37, 42)); // Select first
["i32", "i64"].forEach(t => testEqzSelect(1, t, 42, 37, 37)); // Select second

function testCmpSelect(value, type, iftrue, iffalse, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (select (i32.const ${iftrue})
			            (i32.const ${iffalse})
			            (${type}.eq (local.get 0) (${type}.const ${value}))))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64", "f32", "f64"].forEach(t => testCmpSelect(0, t, 42, 37, 42)); // Select first
["i32", "i64", "f32", "f64"].forEach(t => testCmpSelect(1, t, 42, 37, 37)); // Select second

function testEqzIf(value, type, trueBranch, falseBranch, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (local i32)
			    (local.set 0 (${type}.const ${value}))
			    (if (${type}.eqz (local.get 0))
				(then (local.set 1 (i32.const ${trueBranch})))
			        (else (local.set 1 (i32.const ${falseBranch}))))
			    (local.get 1))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64"].forEach(t => testEqzIf(0, t, 42, 37, 42)); // Taken
["i32", "i64"].forEach(t => testEqzIf(1, t, 42, 37, 37)); // Untaken

function testCmpIf(value, type, trueBranch, falseBranch, expected) {
    var f = wasmEvalText(`(module
			   (func (result i32)
			    (local ${type})
			    (local i32)
			    (if (${type}.eq (local.get 0) (${type}.const ${value}))
				(then (local.set 1 (i32.const ${trueBranch})))
			        (else (local.set 1 (i32.const ${falseBranch}))))
			    (local.get 1))
			   (export "f" (func 0)))`).exports["f"];
    assertEq(f(), expected);
}

["i32", "i64", "f32", "f64"].forEach(t => testCmpIf(0, t, 42, 37, 42)); // Taken
["i32", "i64", "f32", "f64"].forEach(t => testCmpIf(1, t, 42, 37, 37)); // Untaken