Bug 1328127: Fold br_table with all-same-successors into a goto in wasm; r=luke
authorBenjamin Bouvier <benj@benj.me>
Wed, 04 Jan 2017 18:20:07 +0100
changeset 328127 0fe0b5c910f78edfd08b4230393f75968924dd0b
parent 328126 c6a6571e746898347b4de5887cdfdbbcf491a363
child 328128 d2e85dc48786918c91c9bfd1d44fed9fb9ddc5c4
push id31163
push userkwierso@gmail.com
push dateFri, 06 Jan 2017 01:30:45 +0000
treeherdermozilla-central@a14094edbad7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1328127
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1328127: Fold br_table with all-same-successors into a goto in wasm; r=luke 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
@@ -1825,33 +1825,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;