Bug 1286816 - wasm baseline, test cases for boolean optimization for control. r=h4writer
authorLars T Hansen <lhansen@mozilla.com>
Fri, 18 Nov 2016 10:56:10 +0100
changeset 324428 2b4ee4fa6f1939f34dd8ee4c46f49855d613fd3c
parent 324427 3c9d3d8df078b513149aa0228621dad461abe94d
child 324429 c7dc06c5f56aa301af64092ce75033a6e7d9b0a4
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersh4writer
bugs1286816
milestone53.0a1
Bug 1286816 - wasm baseline, test cases for boolean optimization for control. r=h4writer
js/src/jit-test/tests/wasm/baseline-opt.js
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/baseline-opt.js
@@ -0,0 +1,110 @@
+// Point-testing various optimizations in the wasm baseline compiler.
+
+load(libdir + "wasm.js");
+
+// 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)
+			    (set_local 0 (${type}.const ${value}))
+			    (set_local 1 (i32.const ${taken}))
+			    (block $b
+			     (br_if $b (${type}.eqz (get_local 0)))
+			     (set_local 1 (i32.const ${untaken})))
+			    (get_local 1))
+			   (export "f" 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)
+			    (set_local 1 (i32.const ${taken}))
+			    (block $b
+			     (br_if $b (${type}.eq (get_local 0) (${type}.const ${value})))
+			     (set_local 1 (i32.const ${untaken})))
+			    (get_local 1))
+			   (export "f" 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})
+			    (set_local 0 (${type}.const ${value}))
+			    (select (i32.const ${iftrue})
+			            (i32.const ${iffalse})
+			            (${type}.eqz (get_local 0))))
+			   (export "f" 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 (get_local 0) (${type}.const ${value}))))
+			   (export "f" 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)
+			    (set_local 0 (${type}.const ${value}))
+			    (if (${type}.eqz (get_local 0))
+				(set_local 1 (i32.const ${trueBranch}))
+			        (set_local 1 (i32.const ${falseBranch})))
+			    (get_local 1))
+			   (export "f" 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 (get_local 0) (${type}.const ${value}))
+				(set_local 1 (i32.const ${trueBranch}))
+			        (set_local 1 (i32.const ${falseBranch})))
+			    (get_local 1))
+			   (export "f" 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