Bug 1328127: Fold br_table with all-same-successors into a goto in wasm; r=luke a=jcristau
MozReview-Commit-ID: 7DDNWYXKzSv
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;