Bug 1328127: Fold br_table with all-same-successors into a goto in wasm; r=luke a=jcristau
authorBenjamin Bouvier <benj@benj.me>
Wed, 04 Jan 2017 18:20:07 +0100
changeset 350110 1225f99f2ba9356d38a08d9282134a6d1e1e3e5f
parent 350109 072acb55b6690c52a4427005e35ce8dde0ca8027
child 350111 08a4d4135acdf49e0db6670e1cca550767fbe2f4
push id10547
push userkwierso@gmail.com
push dateTue, 10 Jan 2017 00:24:57 +0000
treeherdermozilla-aurora@08a4d4135acd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, jcristau
bugs1328127
milestone52.0a2
Bug 1328127: Fold br_table with all-same-successors into a goto in wasm; r=luke a=jcristau MozReview-Commit-ID: 7DDNWYXKzSv
js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js
js/src/wasm/WasmIonCompile.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/regress/brtable-conditionblock-folding.js
@@ -0,0 +1,19 @@
+load(libdir + "wasm.js");
+
+assertEq(wasmEvalText(`
+(module
+  (func $f (param $p i32)
+    block $out
+      i32.const 0
+      if
+        i32.const 1
+        tee_local $p
+        br_table $out $out
+      end
+    end
+    get_local $p
+    br_if 0
+  )
+  (export "f" $f)
+)
+`).exports.f(42), undefined);
--- a/js/src/wasm/WasmIonCompile.cpp
+++ b/js/src/wasm/WasmIonCompile.cpp
@@ -1830,33 +1830,45 @@ EmitBrTable(FunctionCompiler& f)
     MDefinition* index;
     if (!f.iter().readBrTable(&tableLength, &type, &value, &index))
         return false;
 
     Uint32Vector depths;
     if (!depths.reserve(tableLength))
         return false;
 
-    uint32_t depth;
     for (size_t i = 0; i < tableLength; ++i) {
+        uint32_t depth;
         if (!f.iter().readBrTableEntry(&type, &value, &depth))
             return false;
         depths.infallibleAppend(depth);
     }
 
     // Read the default label.
-    if (!f.iter().readBrTableDefault(&type, &value, &depth))
+    uint32_t defaultDepth;
+    if (!f.iter().readBrTableDefault(&type, &value, &defaultDepth))
         return false;
 
     MDefinition* maybeValue = IsVoid(type) ? nullptr : value;
 
-    if (tableLength == 0)
-        return f.br(depth, maybeValue);
-
-    return f.brTable(index, depth, depths, maybeValue);
+    // If all the targets are the same, or there are no targets, we can just
+    // use a goto. This is not just an optimization: MaybeFoldConditionBlock
+    // assumes that tables have more than one successor.
+    bool allSameDepth = true;
+    for (uint32_t depth : depths) {
+        if (depth != defaultDepth) {
+            allSameDepth = false;
+            break;
+        }
+    }
+
+    if (allSameDepth)
+        return f.br(defaultDepth, maybeValue);
+
+    return f.brTable(index, defaultDepth, depths, maybeValue);
 }
 
 static bool
 EmitReturn(FunctionCompiler& f)
 {
     MDefinition* value;
     if (!f.iter().readReturn(&value))
         return false;