summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/CMakeLists.txt1
-rw-r--r--src/ast/LocalGraph.cpp260
-rw-r--r--src/ast/find_all.h48
-rw-r--r--src/ast/local-graph.h111
-rw-r--r--src/literal.h6
-rw-r--r--src/passes/Inlining.cpp1
-rw-r--r--src/passes/Precompute.cpp148
-rw-r--r--src/passes/SSAify.cpp292
-rw-r--r--src/passes/pass.cpp8
-rw-r--r--src/passes/passes.h1
-rw-r--r--src/tools/execution-results.h14
-rw-r--r--src/tools/wasm-shell.cpp4
-rw-r--r--src/wasm/literal.cpp6
-rw-r--r--test/emcc_hello_world.fromasm12
-rw-r--r--test/emcc_hello_world.fromasm.clamp12
-rw-r--r--test/passes/Oz.txt25
-rw-r--r--test/passes/Oz.wast9
-rw-r--r--test/passes/inlining-optimizing_optimize-level=3.txt492
-rw-r--r--test/passes/precompute-propagate.txt214
-rw-r--r--test/passes/precompute-propagate.wast113
-rw-r--r--test/unit.asm.js61
-rw-r--r--test/unit.fromasm117
-rw-r--r--test/unit.fromasm.clamp117
-rw-r--r--test/unit.fromasm.clamp.no-opts98
-rw-r--r--test/unit.fromasm.imprecise96
-rw-r--r--test/unit.fromasm.imprecise.no-opts98
-rw-r--r--test/unit.fromasm.no-opts98
-rw-r--r--test/wasm-only.fromasm70
-rw-r--r--test/wasm-only.fromasm.clamp70
29 files changed, 1688 insertions, 914 deletions
diff --git a/src/ast/CMakeLists.txt b/src/ast/CMakeLists.txt
index e48e84eed..c01deaaaf 100644
--- a/src/ast/CMakeLists.txt
+++ b/src/ast/CMakeLists.txt
@@ -1,5 +1,6 @@
SET(ast_SOURCES
ExpressionAnalyzer.cpp
ExpressionManipulator.cpp
+ LocalGraph.cpp
)
ADD_LIBRARY(ast STATIC ${ast_SOURCES})
diff --git a/src/ast/LocalGraph.cpp b/src/ast/LocalGraph.cpp
new file mode 100644
index 000000000..c997eff1b
--- /dev/null
+++ b/src/ast/LocalGraph.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <iterator>
+
+#include <wasm-builder.h>
+#include <ast/find_all.h>
+#include <ast/local-graph.h>
+
+namespace wasm {
+
+LocalGraph::LocalGraph(Function* func, Module* module) {
+ walkFunctionInModule(func, module);
+}
+
+void LocalGraph::computeInfluences() {
+ for (auto& pair : locations) {
+ auto* curr = pair.first;
+ if (auto* set = curr->dynCast<SetLocal>()) {
+ FindAll<GetLocal> findAll(set->value);
+ for (auto* get : findAll.list) {
+ getInfluences[get].insert(set);
+ }
+ } else {
+ auto* get = curr->cast<GetLocal>();
+ for (auto* set : getSetses[get]) {
+ setInfluences[set].insert(get);
+ }
+ }
+ }
+}
+
+void LocalGraph::doWalkFunction(Function* func) {
+ numLocals = func->getNumLocals();
+ if (numLocals == 0) return; // nothing to do
+ // We begin with each param being assigned from the incoming value, and the zero-init for the locals,
+ // so the initial state is the identity permutation
+ currMapping.resize(numLocals);
+ for (auto& set : currMapping) {
+ set = { nullptr };
+ }
+ PostWalker<LocalGraph>::walk(func->body);
+}
+
+// control flow
+
+void LocalGraph::visitBlock(Block* curr) {
+ if (curr->name.is() && breakMappings.find(curr->name) != breakMappings.end()) {
+ auto& infos = breakMappings[curr->name];
+ infos.emplace_back(std::move(currMapping));
+ currMapping = std::move(merge(infos));
+ breakMappings.erase(curr->name);
+ }
+}
+
+void LocalGraph::finishIf() {
+ // that's it for this if, merge
+ std::vector<Mapping> breaks;
+ breaks.emplace_back(std::move(currMapping));
+ breaks.emplace_back(std::move(mappingStack.back()));
+ mappingStack.pop_back();
+ currMapping = std::move(merge(breaks));
+}
+
+void LocalGraph::afterIfCondition(LocalGraph* self, Expression** currp) {
+ self->mappingStack.push_back(self->currMapping);
+}
+void LocalGraph::afterIfTrue(LocalGraph* self, Expression** currp) {
+ auto* curr = (*currp)->cast<If>();
+ if (curr->ifFalse) {
+ auto afterCondition = std::move(self->mappingStack.back());
+ self->mappingStack.back() = std::move(self->currMapping);
+ self->currMapping = std::move(afterCondition);
+ } else {
+ self->finishIf();
+ }
+}
+void LocalGraph::afterIfFalse(LocalGraph* self, Expression** currp) {
+ self->finishIf();
+}
+void LocalGraph::beforeLoop(LocalGraph* self, Expression** currp) {
+ // save the state before entering the loop, for calculation later of the merge at the loop top
+ self->mappingStack.push_back(self->currMapping);
+ self->loopGetStack.push_back({});
+}
+void LocalGraph::visitLoop(Loop* curr) {
+ if (curr->name.is() && breakMappings.find(curr->name) != breakMappings.end()) {
+ auto& infos = breakMappings[curr->name];
+ infos.emplace_back(std::move(mappingStack.back()));
+ auto before = infos.back();
+ auto& merged = merge(infos);
+ // every local we created a phi for requires us to update get_local operations in
+ // the loop - the branch back has means that gets in the loop have potentially
+ // more sets reaching them.
+ // we can detect this as follows: if a get of oldIndex has the same sets
+ // as the sets at the entrance to the loop, then it is affected by the loop
+ // header sets, and we can add to there sets that looped back
+ auto linkLoopTop = [&](Index i, Sets& getSets) {
+ auto& beforeSets = before[i];
+ if (getSets.size() < beforeSets.size()) {
+ // the get trivially has fewer sets, so it overrode the loop entry sets
+ return;
+ }
+ std::vector<SetLocal*> intersection;
+ std::set_intersection(beforeSets.begin(), beforeSets.end(),
+ getSets.begin(), getSets.end(),
+ std::back_inserter(intersection));
+ if (intersection.size() < beforeSets.size()) {
+ // the get has not the same sets as in the loop entry
+ return;
+ }
+ // the get has the entry sets, so add any new ones
+ for (auto* set : merged[i]) {
+ getSets.insert(set);
+ }
+ };
+ auto& gets = loopGetStack.back();
+ for (auto* get : gets) {
+ linkLoopTop(get->index, getSetses[get]);
+ }
+ // and the same for the loop fallthrough: any local that still has the
+ // entry sets should also have the loop-back sets as well
+ for (Index i = 0; i < numLocals; i++) {
+ linkLoopTop(i, currMapping[i]);
+ }
+ // finally, breaks still in flight must be updated too
+ for (auto& iter : breakMappings) {
+ auto name = iter.first;
+ if (name == curr->name) continue; // skip our own (which is still in use)
+ auto& mappings = iter.second;
+ for (auto& mapping : mappings) {
+ for (Index i = 0; i < numLocals; i++) {
+ linkLoopTop(i, mapping[i]);
+ }
+ }
+ }
+ // now that we are done with using the mappings, erase our own
+ breakMappings.erase(curr->name);
+ }
+ mappingStack.pop_back();
+ loopGetStack.pop_back();
+}
+void LocalGraph::visitBreak(Break* curr) {
+ if (curr->condition) {
+ breakMappings[curr->name].emplace_back(currMapping);
+ } else {
+ breakMappings[curr->name].emplace_back(std::move(currMapping));
+ setUnreachable(currMapping);
+ }
+}
+void LocalGraph::visitSwitch(Switch* curr) {
+ std::set<Name> all;
+ for (auto target : curr->targets) {
+ all.insert(target);
+ }
+ all.insert(curr->default_);
+ for (auto target : all) {
+ breakMappings[target].emplace_back(currMapping);
+ }
+ setUnreachable(currMapping);
+}
+void LocalGraph::visitReturn(Return *curr) {
+ setUnreachable(currMapping);
+}
+void LocalGraph::visitUnreachable(Unreachable *curr) {
+ setUnreachable(currMapping);
+}
+
+// local usage
+
+void LocalGraph::visitGetLocal(GetLocal* curr) {
+ assert(currMapping.size() == numLocals);
+ assert(curr->index < numLocals);
+ for (auto& loopGets : loopGetStack) {
+ loopGets.push_back(curr);
+ }
+ // current sets are our sets
+ getSetses[curr] = currMapping[curr->index];
+ locations[curr] = getCurrentPointer();
+}
+void LocalGraph::visitSetLocal(SetLocal* curr) {
+ assert(currMapping.size() == numLocals);
+ assert(curr->index < numLocals);
+ // current sets are just this set
+ currMapping[curr->index] = { curr }; // TODO optimize?
+ locations[curr] = getCurrentPointer();
+}
+
+// traversal
+
+void LocalGraph::scan(LocalGraph* self, Expression** currp) {
+ if (auto* iff = (*currp)->dynCast<If>()) {
+ // if needs special handling
+ if (iff->ifFalse) {
+ self->pushTask(LocalGraph::afterIfFalse, currp);
+ self->pushTask(LocalGraph::scan, &iff->ifFalse);
+ }
+ self->pushTask(LocalGraph::afterIfTrue, currp);
+ self->pushTask(LocalGraph::scan, &iff->ifTrue);
+ self->pushTask(LocalGraph::afterIfCondition, currp);
+ self->pushTask(LocalGraph::scan, &iff->condition);
+ } else {
+ PostWalker<LocalGraph>::scan(self, currp);
+ }
+
+ // loops need pre-order visiting too
+ if ((*currp)->is<Loop>()) {
+ self->pushTask(LocalGraph::beforeLoop, currp);
+ }
+}
+
+// helpers
+
+void LocalGraph::setUnreachable(Mapping& mapping) {
+ mapping.resize(numLocals); // may have been emptied by a move
+ mapping[0].clear();
+}
+
+bool LocalGraph::isUnreachable(Mapping& mapping) {
+ // we must have some set for each index, if only the zero init, so empty means we emptied it for unreachable code
+ return mapping[0].empty();
+}
+
+// merges a bunch of infos into one.
+// if we need phis, writes them into the provided vector. the caller should
+// ensure those are placed in the right location
+LocalGraph::Mapping& LocalGraph::merge(std::vector<Mapping>& mappings) {
+ assert(mappings.size() > 0);
+ auto& out = mappings[0];
+ if (mappings.size() == 1) {
+ return out;
+ }
+ // merge into the first
+ for (Index j = 1; j < mappings.size(); j++) {
+ auto& other = mappings[j];
+ for (Index i = 0; i < numLocals; i++) {
+ auto& outSets = out[i];
+ for (auto* set : other[i]) {
+ outSets.insert(set);
+ }
+ }
+ }
+ return out;
+}
+
+} // namespace wasm
+
diff --git a/src/ast/find_all.h b/src/ast/find_all.h
new file mode 100644
index 000000000..98fe4c5a7
--- /dev/null
+++ b/src/ast/find_all.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ast_find_all_h
+#define wasm_ast_find_all_h
+
+#include <wasm-traversal.h>
+
+namespace wasm {
+
+// Find all instances of a certain node type
+
+template<typename T>
+struct FindAll {
+ std::vector<T*> list;
+
+ FindAll(Expression* ast) {
+ struct Finder : public PostWalker<Finder, UnifiedExpressionVisitor<Finder>> {
+ std::vector<T*>* list;
+ void visitExpression(Expression* curr) {
+ if (curr->is<T>()) {
+ (*list).push_back(curr->cast<T>());
+ }
+ }
+ };
+ Finder finder;
+ finder.list = &list;
+ finder.walk(ast);
+ }
+};
+
+} // namespace wasm
+
+#endif // wasm_ast_find_all_h
+
diff --git a/src/ast/local-graph.h b/src/ast/local-graph.h
new file mode 100644
index 000000000..03915da5e
--- /dev/null
+++ b/src/ast/local-graph.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ast_local_graph_h
+#define wasm_ast_local_graph_h
+
+namespace wasm {
+
+//
+// Finds the connections between get_locals and set_locals, creating
+// a graph of those ties. This is useful for "ssa-style" optimization,
+// in which you want to know exactly which sets are relevant for a
+// a get, so it is as if each get has just one set, logically speaking
+// (see the SSA pass for actually creating new local indexes based
+// on this).
+//
+// TODO: the algorithm here is pretty simple, but also pretty slow,
+// we should optimize it. e.g. we rely on set_interaction
+// here, and worse we only use it to compute the size...
+struct LocalGraph : public PostWalker<LocalGraph> {
+ // main API
+
+ // the constructor computes getSetses, the sets affecting each get
+ LocalGraph(Function* func, Module* module);
+
+ // the set_locals relevant for an index or a get.
+ typedef std::set<SetLocal*> Sets;
+
+ // externally useful information
+ std::map<GetLocal*, Sets> getSetses; // the sets affecting each get. a nullptr set means the initial
+ // value (0 for a var, the received value for a param)
+ std::map<Expression*, Expression**> locations; // where each get and set is (for easy replacing)
+
+ // optional computation: compute the influence graphs between sets and gets
+ // (useful for algorithms that propagate changes)
+
+ std::unordered_map<GetLocal*, std::unordered_set<SetLocal*>> getInfluences; // for each get, the sets whose values are influenced by that get
+ std::unordered_map<SetLocal*, std::unordered_set<GetLocal*>> setInfluences; // for each set, the gets whose values are influenced by that set
+
+ void computeInfluences();
+
+private:
+ // we map local index => the set_locals for that index.
+ // a nullptr set means there is a virtual set, from a param
+ // initial value or the zero init initial value.
+ typedef std::vector<Sets> Mapping;
+
+ // internal state
+ Index numLocals;
+ Mapping currMapping;
+ std::vector<Mapping> mappingStack; // used in ifs, loops
+ std::map<Name, std::vector<Mapping>> breakMappings; // break target => infos that reach it
+ std::vector<std::vector<GetLocal*>> loopGetStack; // stack of loops, all the gets in each, so we can update them for back branches
+
+public:
+ void doWalkFunction(Function* func);
+
+ // control flow
+
+ void visitBlock(Block* curr);
+
+ void finishIf();
+
+ static void afterIfCondition(LocalGraph* self, Expression** currp);
+ static void afterIfTrue(LocalGraph* self, Expression** currp);
+ static void afterIfFalse(LocalGraph* self, Expression** currp);
+ static void beforeLoop(LocalGraph* self, Expression** currp);
+ void visitLoop(Loop* curr);
+ void visitBreak(Break* curr);
+ void visitSwitch(Switch* curr);
+ void visitReturn(Return *curr);
+ void visitUnreachable(Unreachable *curr);
+
+ // local usage
+
+ void visitGetLocal(GetLocal* curr);
+ void visitSetLocal(SetLocal* curr);
+
+ // traversal
+
+ static void scan(LocalGraph* self, Expression** currp);
+
+ // helpers
+
+ void setUnreachable(Mapping& mapping);
+
+ bool isUnreachable(Mapping& mapping);
+
+ // merges a bunch of infos into one.
+ // if we need phis, writes them into the provided vector. the caller should
+ // ensure those are placed in the right location
+ Mapping& merge(std::vector<Mapping>& mappings);
+};
+
+} // namespace wasm
+
+#endif // wasm_ast_local_graph_h
+
diff --git a/src/literal.h b/src/literal.h
index 560895e7a..c55d645ad 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -44,7 +44,7 @@ private:
return val & (sizeof(T) * 8 - 1);
}
- public:
+public:
Literal() : type(WasmType::none), i64(0) {}
explicit Literal(WasmType type) : type(type), i64(0) {}
explicit Literal(int32_t init) : type(WasmType::i32), i32(init) {}
@@ -54,6 +54,9 @@ private:
explicit Literal(float init) : type(WasmType::f32), i32(bit_cast<int32_t>(init)) {}
explicit Literal(double init) : type(WasmType::f64), i64(bit_cast<int64_t>(init)) {}
+ bool isConcrete() { return type != none; }
+ bool isNull() { return type == none; }
+
Literal castToF32();
Literal castToF64();
Literal castToI32();
@@ -76,6 +79,7 @@ private:
int64_t getBits() const;
bool operator==(const Literal& other) const;
bool operator!=(const Literal& other) const;
+ bool bitwiseEqual(const Literal& other) const;
static uint32_t NaNPayload(float f);
static uint64_t NaNPayload(double f);
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 192480d26..e5fdcbb9d 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -313,6 +313,7 @@ struct Inlining : public Pass {
PassRunner runner(module, parentRunner->options);
runner.setIsNested(true);
runner.setValidateGlobally(false); // not a full valid module
+ runner.add("precompute-propagate");
runner.add("remove-unused-brs");
runner.add("remove-unused-names");
runner.add("coalesce-locals");
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index c4702fdeb..72292c730 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -23,15 +23,24 @@
#include <wasm-builder.h>
#include <wasm-interpreter.h>
#include <ast_utils.h>
-#include "ast/manipulation.h"
+#include <ast/literal-utils.h>
+#include <ast/local-graph.h>
+#include <ast/manipulation.h>
namespace wasm {
static const Name NONSTANDALONE_FLOW("Binaryen|nonstandalone");
+typedef std::unordered_map<GetLocal*, Literal> GetValues;
+
// Execute an expression by itself. Errors if we hit anything we need anything not in the expression itself standalone.
class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionRunner> {
+ // map gets to constant values, if they are known to be constant
+ GetValues& getValues;
+
public:
+ StandaloneExpressionRunner(GetValues& getValues) : getValues(getValues) {}
+
struct NonstandaloneException {}; // TODO: use a flow with a special name, as this is likely very slow
Flow visitLoop(Loop* curr) {
@@ -50,6 +59,13 @@ public:
return Flow(NONSTANDALONE_FLOW);
}
Flow visitGetLocal(GetLocal *curr) {
+ auto iter = getValues.find(curr);
+ if (iter != getValues.end()) {
+ auto value = iter->second;
+ if (value.isConcrete()) {
+ return Flow(value);
+ }
+ }
return Flow(NONSTANDALONE_FLOW);
}
Flow visitSetLocal(SetLocal *curr) {
@@ -85,17 +101,30 @@ public:
struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVisitor<Precompute>>> {
bool isFunctionParallel() override { return true; }
- Pass* create() override { return new Precompute; }
+ Pass* create() override { return new Precompute(propagate); }
+
+ bool propagate = false;
+
+ Precompute(bool propagate) : propagate(propagate) {}
+
+ GetValues getValues;
+
+ void doWalkFunction(Function* func) {
+ // with extra effort, we can utilize the get-set graph to precompute
+ // things that use locals that are known to be constant. otherwise,
+ // we just look at what is immediately before us
+ if (propagate) {
+ optimizeLocals(func, getModule());
+ }
+ // do the main and final walk over everything
+ WalkerPass<PostWalker<Precompute, UnifiedExpressionVisitor<Precompute>>>::doWalkFunction(func);
+ }
void visitExpression(Expression* curr) {
+ // TODO: if get_local, only replace with a constant if we don't care about size...?
if (curr->is<Const>() || curr->is<Nop>()) return;
// try to evaluate this into a const
- Flow flow;
- try {
- flow = StandaloneExpressionRunner().visit(curr);
- } catch (StandaloneExpressionRunner::NonstandaloneException& e) {
- return;
- }
+ Flow flow = precomputeFlow(curr);
if (flow.breaking()) {
if (flow.breakTo == NONSTANDALONE_FLOW) return;
if (flow.breakTo == RETURN_FLOW) {
@@ -157,10 +186,111 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi
// removing breaks can alter types
ReFinalize().walkFunctionInModule(curr, getModule());
}
+
+private:
+ Flow precomputeFlow(Expression* curr) {
+ try {
+ return StandaloneExpressionRunner(getValues).visit(curr);
+ } catch (StandaloneExpressionRunner::NonstandaloneException& e) {
+ return Flow(NONSTANDALONE_FLOW);
+ }
+ }
+
+ Literal precomputeValue(Expression* curr) {
+ Flow flow = precomputeFlow(curr);
+ if (flow.breaking()) {
+ return Literal();
+ }
+ return flow.value;
+ }
+
+ void optimizeLocals(Function* func, Module* module) {
+ // using the graph of get-set interactions, do a constant-propagation type
+ // operation: note which sets are assigned locals, then see if that lets us
+ // compute other sets as locals (since some of the gets they read may be
+ // constant).
+ // compute all dependencies
+ LocalGraph localGraph(func, module);
+ localGraph.computeInfluences();
+ // prepare the work list. we add things here that might change to a constant
+ // initially, that means everything
+ std::unordered_set<Expression*> work;
+ for (auto& pair : localGraph.locations) {
+ auto* curr = pair.first;
+ work.insert(curr);
+ }
+ std::unordered_map<SetLocal*, Literal> setValues; // the constant value, or none if not a constant
+ // propagate constant values
+ while (!work.empty()) {
+ auto iter = work.begin();
+ auto* curr = *iter;
+ work.erase(iter);
+ // see if this set or get is actually a constant value, and if so,
+ // mark it as such and add everything it influences to the work list,
+ // as they may be constant too.
+ if (auto* set = curr->dynCast<SetLocal>()) {
+ if (setValues[set].isConcrete()) continue; // already known constant
+ auto value = setValues[set] = precomputeValue(set->value);
+ if (value.isConcrete()) {
+ for (auto* get : localGraph.setInfluences[set]) {
+ work.insert(get);
+ }
+ }
+ } else {
+ auto* get = curr->cast<GetLocal>();
+ if (getValues[get].isConcrete()) continue; // already known constant
+ // for this get to have constant value, all sets must agree
+ Literal value;
+ bool first = true;
+ for (auto* set : localGraph.getSetses[get]) {
+ Literal curr;
+ if (set == nullptr) {
+ if (getFunction()->isVar(get->index)) {
+ curr = LiteralUtils::makeLiteralZero(getFunction()->getLocalType(get->index));
+ } else {
+ // it's a param, so it's hopeless
+ value = Literal();
+ break;
+ }
+ } else {
+ curr = setValues[set];
+ }
+ if (curr.isNull()) {
+ // not a constant, give up
+ value = Literal();
+ break;
+ }
+ // we found a concrete value. compare with the current one
+ if (first) {
+ value = curr; // this is the first
+ first = false;
+ } else {
+ if (!value.bitwiseEqual(curr)) {
+ // not the same, give up
+ value = Literal();
+ break;
+ }
+ }
+ }
+ // we may have found a value
+ if (value.isConcrete()) {
+ // we did!
+ getValues[get] = value;
+ for (auto* set : localGraph.getInfluences[get]) {
+ work.insert(set);
+ }
+ }
+ }
+ }
+ }
};
Pass *createPrecomputePass() {
- return new Precompute();
+ return new Precompute(false);
+}
+
+Pass *createPrecomputePropagatePass() {
+ return new Precompute(true);
}
} // namespace wasm
diff --git a/src/passes/SSAify.cpp b/src/passes/SSAify.cpp
index 9c9aeb573..a71a75308 100644
--- a/src/passes/SSAify.cpp
+++ b/src/passes/SSAify.cpp
@@ -35,6 +35,7 @@
#include "wasm-builder.h"
#include "support/permutations.h"
#include "ast/literal-utils.h"
+#include "ast/local-graph.h"
namespace wasm {
@@ -44,261 +45,39 @@ SetLocal IMPOSSIBLE_SET;
// Tracks assignments to locals, assuming single-assignment form, i.e.,
// each assignment creates a new variable.
-struct SSAify : public WalkerPass<PostWalker<SSAify>> {
+struct SSAify : public Pass {
bool isFunctionParallel() override { return true; }
Pass* create() override { return new SSAify; }
- // the set_locals relevant for an index or a get. we use
- // as set as merges of control flow mean more than 1 may
- // be relevant; we create a phi on demand when necessary for those
- typedef std::set<SetLocal*> Sets;
-
- // we map (old local index) => the set_locals for that index.
- // a nullptr set means there is a virtual set, from a param
- // initial value or the zero init initial value.
- typedef std::vector<Sets> Mapping;
-
- Index numLocals;
- Mapping currMapping;
- Index nextIndex;
- std::vector<Mapping> mappingStack; // used in ifs, loops
- std::map<Name, std::vector<Mapping>> breakMappings; // break target => infos that reach it
- std::vector<std::vector<GetLocal*>> loopGetStack; // stack of loops, all the gets in each, so we can update them for back branches
+ Module* module;
+ Function* func;
std::vector<Expression*> functionPrepends; // things we add to the function prologue
- std::map<GetLocal*, Sets> getSetses; // the sets for each get
- std::map<GetLocal*, Expression**> getLocations;
- void doWalkFunction(Function* func) {
- numLocals = func->getNumLocals();
- if (numLocals == 0) return; // nothing to do
- // We begin with each param being assigned from the incoming value, and the zero-init for the locals,
- // so the initial state is the identity permutation
- currMapping.resize(numLocals);
- for (auto& set : currMapping) {
- set = { nullptr };
- }
- nextIndex = numLocals;
- WalkerPass<PostWalker<SSAify>>::walk(func->body);
- // apply - we now know the sets for each get
- computeGetsAndPhis();
- // add prepends
- if (functionPrepends.size() > 0) {
- Builder builder(*getModule());
- auto* block = builder.makeBlock();
- for (auto* pre : functionPrepends) {
- block->list.push_back(pre);
+ void runFunction(PassRunner* runner, Module* module_, Function* func_) override {
+ module = module_;
+ func = func_;
+ LocalGraph graph(func, module);
+ // create new local indexes, one for each set
+ createNewIndexes(graph);
+ // we now know the sets for each get
+ computeGetsAndPhis(graph);
+ // add prepends to function
+ addPrepends();
+ }
+
+ void createNewIndexes(LocalGraph& graph) {
+ for (auto& pair : graph.locations) {
+ auto* curr = pair.first;
+ if (auto* set = curr->dynCast<SetLocal>()) {
+ set->index = addLocal(func->getLocalType(set->index));
}
- block->list.push_back(func->body);
- block->finalize(func->body->type);
- func->body = block;
}
}
- // control flow
-
- void visitBlock(Block* curr) {
- if (curr->name.is() && breakMappings.find(curr->name) != breakMappings.end()) {
- auto& infos = breakMappings[curr->name];
- infos.emplace_back(std::move(currMapping));
- currMapping = std::move(merge(infos));
- breakMappings.erase(curr->name);
- }
- }
-
- void finishIf() {
- // that's it for this if, merge
- std::vector<Mapping> breaks;
- breaks.emplace_back(std::move(currMapping));
- breaks.emplace_back(std::move(mappingStack.back()));
- mappingStack.pop_back();
- currMapping = std::move(merge(breaks));
- }
-
- static void afterIfCondition(SSAify* self, Expression** currp) {
- self->mappingStack.push_back(self->currMapping);
- }
- static void afterIfTrue(SSAify* self, Expression** currp) {
- auto* curr = (*currp)->cast<If>();
- if (curr->ifFalse) {
- auto afterCondition = std::move(self->mappingStack.back());
- self->mappingStack.back() = std::move(self->currMapping);
- self->currMapping = std::move(afterCondition);
- } else {
- self->finishIf();
- }
- }
- static void afterIfFalse(SSAify* self, Expression** currp) {
- self->finishIf();
- }
- static void beforeLoop(SSAify* self, Expression** currp) {
- // save the state before entering the loop, for calculation later of the merge at the loop top
- self->mappingStack.push_back(self->currMapping);
- self->loopGetStack.push_back({});
- }
- void visitLoop(Loop* curr) {
- if (curr->name.is() && breakMappings.find(curr->name) != breakMappings.end()) {
- auto& infos = breakMappings[curr->name];
- infos.emplace_back(std::move(mappingStack.back()));
- auto before = infos.back();
- auto& merged = merge(infos);
- // every local we created a phi for requires us to update get_local operations in
- // the loop - the branch back has means that gets in the loop have potentially
- // more sets reaching them.
- // we can detect this as follows: if a get of oldIndex has the same sets
- // as the sets at the entrance to the loop, then it is affected by the loop
- // header sets, and we can add to there sets that looped back
- auto linkLoopTop = [&](Index i, Sets& getSets) {
- auto& beforeSets = before[i];
- if (getSets.size() < beforeSets.size()) {
- // the get trivially has fewer sets, so it overrode the loop entry sets
- return;
- }
- std::vector<SetLocal*> intersection;
- std::set_intersection(beforeSets.begin(), beforeSets.end(),
- getSets.begin(), getSets.end(),
- std::back_inserter(intersection));
- if (intersection.size() < beforeSets.size()) {
- // the get has not the same sets as in the loop entry
- return;
- }
- // the get has the entry sets, so add any new ones
- for (auto* set : merged[i]) {
- getSets.insert(set);
- }
- };
- auto& gets = loopGetStack.back();
- for (auto* get : gets) {
- linkLoopTop(get->index, getSetses[get]);
- }
- // and the same for the loop fallthrough: any local that still has the
- // entry sets should also have the loop-back sets as well
- for (Index i = 0; i < numLocals; i++) {
- linkLoopTop(i, currMapping[i]);
- }
- // finally, breaks still in flight must be updated too
- for (auto& iter : breakMappings) {
- auto name = iter.first;
- if (name == curr->name) continue; // skip our own (which is still in use)
- auto& mappings = iter.second;
- for (auto& mapping : mappings) {
- for (Index i = 0; i < numLocals; i++) {
- linkLoopTop(i, mapping[i]);
- }
- }
- }
- // now that we are done with using the mappings, erase our own
- breakMappings.erase(curr->name);
- }
- mappingStack.pop_back();
- loopGetStack.pop_back();
- }
- void visitBreak(Break* curr) {
- if (curr->condition) {
- breakMappings[curr->name].emplace_back(currMapping);
- } else {
- breakMappings[curr->name].emplace_back(std::move(currMapping));
- setUnreachable(currMapping);
- }
- }
- void visitSwitch(Switch* curr) {
- std::set<Name> all;
- for (auto target : curr->targets) {
- all.insert(target);
- }
- all.insert(curr->default_);
- for (auto target : all) {
- breakMappings[target].emplace_back(currMapping);
- }
- setUnreachable(currMapping);
- }
- void visitReturn(Return *curr) {
- setUnreachable(currMapping);
- }
- void visitUnreachable(Unreachable *curr) {
- setUnreachable(currMapping);
- }
-
- // local usage
-
- void visitGetLocal(GetLocal* curr) {
- assert(currMapping.size() == numLocals);
- assert(curr->index < numLocals);
- for (auto& loopGets : loopGetStack) {
- loopGets.push_back(curr);
- }
- // current sets are our sets
- getSetses[curr] = currMapping[curr->index];
- getLocations[curr] = getCurrentPointer();
- }
- void visitSetLocal(SetLocal* curr) {
- assert(currMapping.size() == numLocals);
- assert(curr->index < numLocals);
- // current sets are just this set
- currMapping[curr->index] = { curr }; // TODO optimize?
- curr->index = addLocal(getFunction()->getLocalType(curr->index));
- }
-
- // traversal
-
- static void scan(SSAify* self, Expression** currp) {
- if (auto* iff = (*currp)->dynCast<If>()) {
- // if needs special handling
- if (iff->ifFalse) {
- self->pushTask(SSAify::afterIfFalse, currp);
- self->pushTask(SSAify::scan, &iff->ifFalse);
- }
- self->pushTask(SSAify::afterIfTrue, currp);
- self->pushTask(SSAify::scan, &iff->ifTrue);
- self->pushTask(SSAify::afterIfCondition, currp);
- self->pushTask(SSAify::scan, &iff->condition);
- } else {
- WalkerPass<PostWalker<SSAify>>::scan(self, currp);
- }
-
- // loops need pre-order visiting too
- if ((*currp)->is<Loop>()) {
- self->pushTask(SSAify::beforeLoop, currp);
- }
- }
-
- // helpers
-
- void setUnreachable(Mapping& mapping) {
- mapping.resize(numLocals); // may have been emptied by a move
- mapping[0].clear();
- }
-
- bool isUnreachable(Mapping& mapping) {
- // we must have some set for each index, if only the zero init, so empty means we emptied it for unreachable code
- return mapping[0].empty();
- }
-
- // merges a bunch of infos into one.
- // if we need phis, writes them into the provided vector. the caller should
- // ensure those are placed in the right location
- Mapping& merge(std::vector<Mapping>& mappings) {
- assert(mappings.size() > 0);
- auto& out = mappings[0];
- if (mappings.size() == 1) {
- return out;
- }
- // merge into the first
- for (Index j = 1; j < mappings.size(); j++) {
- auto& other = mappings[j];
- for (Index i = 0; i < numLocals; i++) {
- auto& outSets = out[i];
- for (auto* set : other[i]) {
- outSets.insert(set);
- }
- }
- }
- return out;
- }
-
// After we traversed it all, we can compute gets and phis
- void computeGetsAndPhis() {
- for (auto& iter : getSetses) {
+ void computeGetsAndPhis(LocalGraph& graph) {
+ for (auto& iter : graph.getSetses) {
auto* get = iter.first;
auto& sets = iter.second;
if (sets.size() == 0) {
@@ -312,11 +91,11 @@ struct SSAify : public WalkerPass<PostWalker<SSAify>> {
get->index = set->index;
} else {
// no set, assign param or zero
- if (getFunction()->isParam(get->index)) {
+ if (func->isParam(get->index)) {
// leave it, it's fine
} else {
// zero it out
- (*getLocations[get]) = LiteralUtils::makeZero(get->type, *getModule());
+ (*graph.locations[get]) = LiteralUtils::makeZero(get->type, *module);
}
}
continue;
@@ -354,7 +133,7 @@ struct SSAify : public WalkerPass<PostWalker<SSAify>> {
auto new_ = addLocal(get->type);
auto old = get->index;
get->index = new_;
- Builder builder(*getModule());
+ Builder builder(*module);
// write to the local in each of our sets
for (auto* set : sets) {
if (set) {
@@ -365,12 +144,12 @@ struct SSAify : public WalkerPass<PostWalker<SSAify>> {
);
} else {
// this is a param or the zero init value.
- if (getFunction()->isParam(old)) {
+ if (func->isParam(old)) {
// we add a set with the proper
// param value at the beginning of the function
auto* set = builder.makeSetLocal(
new_,
- builder.makeGetLocal(old, getFunction()->getLocalType(old))
+ builder.makeGetLocal(old, func->getLocalType(old))
);
functionPrepends.push_back(set);
} else {
@@ -383,7 +162,20 @@ struct SSAify : public WalkerPass<PostWalker<SSAify>> {
}
Index addLocal(WasmType type) {
- return Builder::addVar(getFunction(), type);
+ return Builder::addVar(func, type);
+ }
+
+ void addPrepends() {
+ if (functionPrepends.size() > 0) {
+ Builder builder(*module);
+ auto* block = builder.makeBlock();
+ for (auto* pre : functionPrepends) {
+ block->list.push_back(pre);
+ }
+ block->list.push_back(func->body);
+ block->finalize(func->body->type);
+ func->body = block;
+ }
}
};
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 4ec454a50..a208a03dd 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -89,6 +89,7 @@ void PassRegistry::registerPasses() {
registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
registerPass("post-emscripten", "miscellaneous optimizations for Emscripten-generated code", createPostEmscriptenPass);
registerPass("precompute", "computes compile-time evaluatable expressions", createPrecomputePass);
+ registerPass("precompute-propagate", "computes compile-time evaluatable expressions and propagates them through locals", createPrecomputePropagatePass);
registerPass("print", "print in s-expression format", createPrinterPass);
registerPass("print-minified", "print in minified s-expression format", createMinifiedPrinterPass);
registerPass("print-full", "print in full s-expression format", createFullPrinterPass);
@@ -148,7 +149,12 @@ void PassRunner::addDefaultFunctionOptimizationPasses() {
add("remove-unused-brs"); // coalesce-locals opens opportunities for optimizations
add("merge-blocks"); // clean up remove-unused-brs new blocks
add("optimize-instructions");
- add("precompute");
+ // if we are willing to work hard, also propagate
+ if (options.optimizeLevel >= 3 || options.shrinkLevel >= 2) {
+ add("precompute-propagate");
+ } else {
+ add("precompute");
+ }
if (options.shrinkLevel >= 2) {
add("local-cse"); // TODO: run this early, before first coalesce-locals. right now doing so uncovers some deficiencies we need to fix first
add("coalesce-locals"); // just for localCSE
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 4e039f4bf..a02216083 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -49,6 +49,7 @@ Pass *createOptimizeInstructionsPass();
Pass *createPickLoadSignsPass();
Pass *createPostEmscriptenPass();
Pass *createPrecomputePass();
+Pass *createPrecomputePropagatePass();
Pass *createPrinterPass();
Pass *createPrintCallGraphPass();
Pass *createRelooperJumpThreadingPass();
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index 5ed0ff01f..1fee4ffb0 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -23,18 +23,6 @@
namespace wasm {
-static bool areBitwiseEqual(Literal a, Literal b) {
- if (a == b) return true;
- // accept equal nans if equal in all bits
- if (a.type != b.type) return false;
- if (a.type == f32) {
- return a.reinterpreti32() == b.reinterpreti32();
- } else if (a.type == f64) {
- return a.reinterpreti64() == b.reinterpreti64();
- }
- return false;
-}
-
// gets execution results from a wasm module. this is useful for fuzzing
//
// we can only get results when there are no imports. we then call each method
@@ -86,7 +74,7 @@ struct ExecutionResults {
abort();
}
std::cout << "[fuzz-exec] comparing " << name << '\n';
- if (!areBitwiseEqual(results[name], other.results[name])) {
+ if (!results[name].bitwiseEqual(other.results[name])) {
std::cout << "not identical!\n";
abort();
}
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index b7fde3af6..cd8c27437 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -201,14 +201,14 @@ static void run_asserts(Name moduleName, size_t* i, bool* checked, Module* wasm,
->dynCast<Const>()
->value;
std::cerr << "seen " << result << ", expected " << expected << '\n';
- if (!areBitwiseEqual(expected, result)) {
+ if (!expected.bitwiseEqual(result)) {
std::cout << "unexpected, should be identical\n";
abort();
}
} else {
Literal expected;
std::cerr << "seen " << result << ", expected " << expected << '\n';
- if (!areBitwiseEqual(expected, result)) {
+ if (!expected.bitwiseEqual(result)) {
std::cout << "unexpected, should be identical\n";
abort();
}
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index be1363dde..de89a7ac1 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -93,6 +93,12 @@ bool Literal::operator!=(const Literal& other) const {
return !(*this == other);
}
+bool Literal::bitwiseEqual(const Literal& other) const {
+ if (type != other.type) return false;
+ if (type == none) return true;
+ return getBits() == other.getBits();
+}
+
uint32_t Literal::NaNPayload(float f) {
assert(std::isnan(f) && "expected a NaN");
// SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index e96288365..39e161495 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -5099,15 +5099,9 @@
(i32.lt_s
(tee_local $6
(i32.add
- (if (result i32)
- (tee_local $12
- (i32.const 9)
- )
- (i32.rem_s
- (get_local $6)
- (get_local $12)
- )
- (i32.const 0)
+ (i32.rem_s
+ (get_local $6)
+ (i32.const 9)
)
(i32.const 1)
)
diff --git a/test/emcc_hello_world.fromasm.clamp b/test/emcc_hello_world.fromasm.clamp
index 7ae8bb801..b074afa30 100644
--- a/test/emcc_hello_world.fromasm.clamp
+++ b/test/emcc_hello_world.fromasm.clamp
@@ -5123,15 +5123,9 @@
(i32.lt_s
(tee_local $6
(i32.add
- (if (result i32)
- (tee_local $12
- (i32.const 9)
- )
- (i32.rem_s
- (get_local $6)
- (get_local $12)
- )
- (i32.const 0)
+ (i32.rem_s
+ (get_local $6)
+ (i32.const 9)
)
(i32.const 1)
)
diff --git a/test/passes/Oz.txt b/test/passes/Oz.txt
index c67106326..c76cc0e5c 100644
--- a/test/passes/Oz.txt
+++ b/test/passes/Oz.txt
@@ -1,6 +1,6 @@
(module
(type $0 (func (param i32 i32) (result i32)))
- (type $1 (func (param i32) (result i32)))
+ (type $1 (func (param i32 i32 i32 i32) (result i32)))
(memory $0 100 100)
(export "localcse" (func $basics))
(export "localcse-2" (func $8))
@@ -16,11 +16,11 @@
(get_local $2)
)
)
- (func $8 (type $1) (param $0 i32) (result i32)
- (local $1 i32)
+ (func $8 (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32)
+ (local $4 i32)
(i32.store
- (tee_local $0
- (tee_local $1
+ (tee_local $2
+ (tee_local $4
(i32.add
(get_local $1)
(i32.const 4)
@@ -29,26 +29,23 @@
)
(i32.and
(i32.load
- (get_local $0)
+ (get_local $2)
)
(i32.xor
- (tee_local $0
- (i32.const 74)
- )
+ (i32.const 74)
(i32.const -1)
)
)
)
(i32.store
- (get_local $1)
+ (tee_local $1
+ (get_local $4)
+ )
(i32.or
(i32.load
(get_local $1)
)
- (i32.and
- (get_local $0)
- (i32.const 8)
- )
+ (i32.const 8)
)
)
(i32.const 0)
diff --git a/test/passes/Oz.wast b/test/passes/Oz.wast
index 2bb8934c4..5ba6a7ea5 100644
--- a/test/passes/Oz.wast
+++ b/test/passes/Oz.wast
@@ -11,10 +11,11 @@
)
(i32.add (get_local $x2) (get_local $y2))
)
- (func $8 (export "localcse-2") (param $var$0 i32) (result i32)
- (local $var$1 i32)
- (local $var$2 i32)
- (local $var$3 i32)
+ (func $8 (export "localcse-2") (param $var$0 i32)
+ (param $var$1 i32)
+ (param $var$2 i32)
+ (param $var$3 i32)
+ (result i32)
(block $label$0 (result i32)
(i32.store
(tee_local $var$2
diff --git a/test/passes/inlining-optimizing_optimize-level=3.txt b/test/passes/inlining-optimizing_optimize-level=3.txt
index 711451bcd..d9583cbb3 100644
--- a/test/passes/inlining-optimizing_optimize-level=3.txt
+++ b/test/passes/inlining-optimizing_optimize-level=3.txt
@@ -2231,7 +2231,6 @@
(local $49 i32)
(local $50 i32)
(local $51 i32)
- (local $52 i32)
(set_local $26
(get_global $STACKTOP)
)
@@ -2263,7 +2262,7 @@
(i32.const 528)
)
)
- (set_local $31
+ (set_local $30
(i32.ne
(get_local $0)
(i32.const 0)
@@ -2288,7 +2287,7 @@
(i32.const 39)
)
)
- (set_local $47
+ (set_local $46
(i32.add
(tee_local $43
(i32.add
@@ -2316,7 +2315,7 @@
(i32.const 11)
)
)
- (set_local $48
+ (set_local $47
(i32.sub
(tee_local $29
(get_local $36)
@@ -2331,21 +2330,21 @@
)
)
)
- (set_local $49
+ (set_local $48
(i32.sub
(i32.const -2)
(get_local $39)
)
)
- (set_local $50
+ (set_local $49
(i32.add
(get_local $29)
(i32.const 2)
)
)
- (set_local $52
+ (set_local $51
(i32.add
- (tee_local $51
+ (tee_local $50
(i32.add
(get_local $26)
(i32.const 24)
@@ -2355,7 +2354,7 @@
)
)
(set_local $45
- (tee_local $32
+ (tee_local $31
(i32.add
(get_local $24)
(i32.const 9)
@@ -2374,7 +2373,7 @@
(set_local $5
(get_local $1)
)
- (set_local $11
+ (set_local $10
(i32.const 0)
)
(set_local $1
@@ -2392,7 +2391,7 @@
(set_local $16
(if (result i32)
(i32.gt_s
- (get_local $11)
+ (get_local $10)
(i32.sub
(i32.const 2147483647)
(get_local $16)
@@ -2414,7 +2413,7 @@
(i32.const -1)
)
(i32.add
- (get_local $11)
+ (get_local $10)
(get_local $16)
)
)
@@ -2429,7 +2428,7 @@
)
)
)
- (set_local $11
+ (set_local $10
(get_local $5)
)
(block $label$break$L12
@@ -2450,20 +2449,20 @@
)
)
(set_local $6
- (get_local $11)
+ (get_local $10)
)
(br $__rjti$1)
)
(set_local $6
- (get_local $11)
+ (get_local $10)
)
(br $label$break$L9)
)
(set_local $7
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -2483,9 +2482,9 @@
(i32.const 37)
)
)
- (set_local $11
+ (set_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -2506,12 +2505,12 @@
)
(set_local $7
(i32.sub
- (get_local $11)
+ (get_local $10)
(get_local $5)
)
)
(if
- (get_local $31)
+ (get_local $30)
(if
(i32.eqz
(i32.and
@@ -2532,14 +2531,14 @@
)
(if
(i32.ne
- (get_local $11)
+ (get_local $10)
(get_local $5)
)
(block
(set_local $5
(get_local $6)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -2552,7 +2551,7 @@
(i32.add
(tee_local $12
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(i32.add
(get_local $6)
(i32.const 1)
@@ -2568,13 +2567,13 @@
(block (result i32)
(set_local $6
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(select
(i32.add
(get_local $6)
(i32.const 3)
)
- (get_local $11)
+ (get_local $10)
(tee_local $12
(i32.eq
(i32.load8_s offset=2
@@ -2686,9 +2685,9 @@
(tee_local $6
(tee_local $1
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -2723,7 +2722,7 @@
(i32.const 42)
)
(block
- (set_local $11
+ (set_local $10
(block $__rjto$0 (result i32)
(block $__rjti$0
(br_if $__rjti$0
@@ -2733,7 +2732,7 @@
(i32.load8_s
(tee_local $6
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -2747,7 +2746,7 @@
(br_if $__rjti$0
(i32.ne
(i32.load8_s offset=2
- (get_local $11)
+ (get_local $10)
)
(i32.const 36)
)
@@ -2790,7 +2789,7 @@
)
(br $__rjto$0
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 3)
)
)
@@ -2806,13 +2805,13 @@
)
(if
(i32.eqz
- (get_local $31)
+ (get_local $30)
)
(block
(set_local $12
(get_local $1)
)
- (set_local $11
+ (set_local $10
(get_local $6)
)
(set_local $1
@@ -2826,7 +2825,7 @@
)
(set_local $14
(i32.load
- (tee_local $11
+ (tee_local $10
(i32.and
(i32.add
(i32.load
@@ -2842,7 +2841,7 @@
(i32.store
(get_local $2)
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 4)
)
)
@@ -2912,9 +2911,9 @@
(tee_local $9
(i32.add
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -2978,7 +2977,7 @@
(if (result i32)
(i32.eq
(i32.load8_s
- (get_local $11)
+ (get_local $10)
)
(i32.const 46)
)
@@ -2989,7 +2988,7 @@
(i32.load8_s
(tee_local $6
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -3009,7 +3008,7 @@
(i32.const 10)
)
(block
- (set_local $11
+ (set_local $10
(get_local $6)
)
(set_local $8
@@ -3020,7 +3019,7 @@
)
)
(block
- (set_local $11
+ (set_local $10
(get_local $6)
)
(br $label$break$L46
@@ -3044,9 +3043,9 @@
(tee_local $9
(i32.add
(i32.load8_s
- (tee_local $11
+ (tee_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 1)
)
)
@@ -3075,7 +3074,7 @@
(i32.load8_s
(tee_local $6
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 2)
)
)
@@ -3088,7 +3087,7 @@
(if
(i32.eq
(i32.load8_s offset=3
- (get_local $11)
+ (get_local $10)
)
(i32.const 36)
)
@@ -3121,9 +3120,9 @@
)
)
)
- (set_local $11
+ (set_local $10
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 4)
)
)
@@ -3145,11 +3144,11 @@
)
)
(if (result i32)
- (get_local $31)
+ (get_local $30)
(block (result i32)
(set_local $8
(i32.load
- (tee_local $11
+ (tee_local $10
(i32.and
(i32.add
(i32.load
@@ -3165,17 +3164,17 @@
(i32.store
(get_local $2)
(i32.add
- (get_local $11)
+ (get_local $10)
(i32.const 4)
)
)
- (set_local $11
+ (set_local $10
(get_local $6)
)
(get_local $8)
)
(block (result i32)
- (set_local $11
+ (set_local $10
(get_local $6)
)
(i32.const 0)
@@ -3187,7 +3186,7 @@
)
)
(set_local $8
- (get_local $11)
+ (get_local $10)
)
(set_local $9
(i32.const 0)
@@ -3195,7 +3194,7 @@
(loop $while-in13
(if
(i32.gt_u
- (tee_local $10
+ (tee_local $11
(i32.add
(i32.load8_s
(get_local $8)
@@ -3212,7 +3211,7 @@
(br $label$break$L1)
)
)
- (set_local $11
+ (set_local $10
(i32.add
(get_local $8)
(i32.const 1)
@@ -3221,7 +3220,7 @@
(if
(i32.lt_u
(i32.add
- (tee_local $10
+ (tee_local $11
(i32.and
(tee_local $13
(i32.load8_s
@@ -3233,7 +3232,7 @@
)
(i32.const 3611)
)
- (get_local $10)
+ (get_local $11)
)
)
)
@@ -3246,10 +3245,10 @@
)
(block
(set_local $8
- (get_local $11)
+ (get_local $10)
)
(set_local $9
- (get_local $10)
+ (get_local $11)
)
(br $while-in13)
)
@@ -3310,11 +3309,11 @@
(i32.const 2)
)
)
- (get_local $10)
+ (get_local $11)
)
(set_local $13
(i32.load offset=4
- (tee_local $10
+ (tee_local $11
(i32.add
(get_local $3)
(i32.shl
@@ -3330,7 +3329,7 @@
(get_local $19)
)
(i32.load
- (get_local $10)
+ (get_local $11)
)
)
(i32.store offset=4
@@ -3342,7 +3341,7 @@
)
(if
(i32.eqz
- (get_local $31)
+ (get_local $30)
)
(block
(set_local $16
@@ -3353,7 +3352,7 @@
)
(call $_pop_arg_336
(get_local $19)
- (get_local $10)
+ (get_local $11)
(get_local $2)
)
)
@@ -3362,13 +3361,13 @@
)
(if
(i32.eqz
- (get_local $31)
+ (get_local $30)
)
(block
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3416,14 +3415,14 @@
(tee_local $18
(select
(i32.and
- (tee_local $10
+ (tee_local $11
(i32.load8_s
(get_local $18)
)
)
(i32.const -33)
)
- (get_local $10)
+ (get_local $11)
(i32.and
(i32.ne
(get_local $9)
@@ -3431,7 +3430,7 @@
)
(i32.eq
(i32.and
- (get_local $10)
+ (get_local $11)
(i32.const 15)
)
(i32.const 3)
@@ -3462,9 +3461,9 @@
(get_local $16)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3476,9 +3475,9 @@
(get_local $16)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3505,9 +3504,9 @@
)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3519,9 +3518,9 @@
(get_local $16)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3533,9 +3532,9 @@
(get_local $16)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3547,9 +3546,9 @@
(get_local $16)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3576,17 +3575,17 @@
)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -3754,16 +3753,12 @@
(set_global $tempRet0
(i32.sub
(i32.sub
- (tee_local $9
- (i32.const 0)
- )
+ (i32.const 0)
(get_local $7)
)
(i32.gt_u
(get_local $5)
- (tee_local $10
- (i32.const 0)
- )
+ (i32.const 0)
)
)
)
@@ -3773,7 +3768,7 @@
)
(tee_local $5
(i32.sub
- (get_local $10)
+ (i32.const 0)
(get_local $5)
)
)
@@ -3863,7 +3858,7 @@
(set_local $12
(get_local $8)
)
- (set_local $10
+ (set_local $11
(i32.const 1)
)
(set_local $8
@@ -3920,7 +3915,7 @@
)
)
(i32.store
- (get_local $47)
+ (get_local $46)
(i32.const 0)
)
(i32.store
@@ -3973,7 +3968,7 @@
(get_global $tempDoublePtr)
)
)
- (set_local $33
+ (set_local $32
(if (result i32)
(i32.lt_s
(i32.load offset=4
@@ -4093,10 +4088,10 @@
(set_local $9
(select
(i32.add
- (get_local $33)
+ (get_local $32)
(i32.const 9)
)
- (get_local $33)
+ (get_local $32)
(tee_local $13
(i32.and
(get_local $18)
@@ -4217,7 +4212,7 @@
)
)
)
- (set_local $10
+ (set_local $11
(i32.or
(get_local $28)
(i32.const 2)
@@ -4380,14 +4375,14 @@
(select
(i32.sub
(i32.add
- (get_local $50)
+ (get_local $49)
(get_local $6)
)
(get_local $8)
)
(i32.add
(i32.sub
- (get_local $48)
+ (get_local $47)
(get_local $8)
)
(get_local $5)
@@ -4399,7 +4394,7 @@
)
(i32.lt_s
(i32.add
- (get_local $49)
+ (get_local $48)
(get_local $5)
)
(get_local $6)
@@ -4407,7 +4402,7 @@
)
)
)
- (get_local $10)
+ (get_local $11)
)
)
(get_local $12)
@@ -4424,7 +4419,7 @@
(drop
(call $___fwritex
(get_local $9)
- (get_local $10)
+ (get_local $11)
(get_local $0)
)
)
@@ -4552,8 +4547,8 @@
(set_local $7
(tee_local $8
(select
+ (get_local $50)
(get_local $51)
- (get_local $52)
(i32.lt_s
(get_local $5)
(i32.const 0)
@@ -4652,7 +4647,7 @@
(get_local $5)
)
(block
- (set_local $10
+ (set_local $11
(i32.const 0)
)
(loop $while-in66
@@ -4675,23 +4670,21 @@
(tee_local $23
(get_global $tempRet0)
)
- (tee_local $30
- (i32.const 0)
- )
+ (i32.const 0)
)
(i32.lt_u
- (tee_local $10
+ (tee_local $11
(i32.add
(get_local $21)
- (get_local $10)
+ (get_local $11)
)
)
(get_local $21)
)
)
)
- (tee_local $10
- (get_local $10)
+ (tee_local $11
+ (get_local $11)
)
)
(tee_local $17
@@ -4701,9 +4694,9 @@
(i32.const 0)
)
)
- (set_local $10
+ (set_local $11
(call $___udivdi3
- (get_local $10)
+ (get_local $11)
(get_local $17)
(i32.const 1000000000)
(i32.const 0)
@@ -4723,7 +4716,7 @@
)
(br_if $do-once63
(i32.eqz
- (get_local $10)
+ (get_local $11)
)
)
(i32.store
@@ -4733,7 +4726,7 @@
(i32.const -4)
)
)
- (get_local $10)
+ (get_local $11)
)
)
)
@@ -4812,32 +4805,23 @@
(set_local $21
(i32.add
(if (result i32)
- (tee_local $10
- (i32.const 9)
- )
- (if (result i32)
- (i32.and
- (i32.eq
- (get_local $6)
- (i32.const -2147483648)
- )
- (i32.eq
- (get_local $10)
- (i32.const -1)
- )
- )
- (i32.const 0)
- (i32.div_s
+ (i32.and
+ (i32.eq
(get_local $6)
- (get_local $10)
+ (i32.const -2147483648)
)
+ (i32.const 0)
)
(i32.const 0)
+ (i32.div_s
+ (get_local $6)
+ (i32.const 9)
+ )
)
(i32.const 1)
)
)
- (set_local $34
+ (set_local $33
(i32.eq
(get_local $25)
(i32.const 102)
@@ -4872,7 +4856,7 @@
(get_local $5)
)
(block
- (set_local $10
+ (set_local $11
(i32.add
(i32.shl
(i32.const 1)
@@ -4898,7 +4882,7 @@
(get_local $7)
(i32.add
(i32.shr_u
- (tee_local $35
+ (tee_local $34
(i32.load
(get_local $7)
)
@@ -4911,8 +4895,8 @@
(set_local $9
(i32.mul
(i32.and
- (get_local $35)
- (get_local $10)
+ (get_local $34)
+ (get_local $11)
)
(get_local $40)
)
@@ -4971,14 +4955,14 @@
)
)
)
- (set_local $10
+ (set_local $11
(select
(i32.add
(tee_local $6
(select
(get_local $8)
(get_local $7)
- (get_local $34)
+ (get_local $33)
)
)
(i32.shl
@@ -5020,7 +5004,7 @@
(get_local $7)
)
(set_local $5
- (get_local $10)
+ (get_local $11)
)
(br $while-in70)
)
@@ -5029,7 +5013,7 @@
(get_local $7)
)
(set_local $9
- (get_local $10)
+ (get_local $11)
)
)
)
@@ -5063,7 +5047,7 @@
)
(br_if $do-once75
(i32.lt_u
- (tee_local $10
+ (tee_local $11
(i32.load
(get_local $5)
)
@@ -5083,7 +5067,7 @@
)
(br_if $while-in78
(i32.ge_u
- (get_local $10)
+ (get_local $11)
(tee_local $6
(i32.mul
(get_local $6)
@@ -5118,7 +5102,7 @@
(i32.shr_s
(i32.shl
(i32.and
- (tee_local $34
+ (tee_local $33
(i32.ne
(get_local $17)
(i32.const 0)
@@ -5152,7 +5136,7 @@
)
)
(block (result i32)
- (set_local $10
+ (set_local $11
(tee_local $6
(i32.add
(get_local $6)
@@ -5162,42 +5146,27 @@
)
(set_local $13
(if (result i32)
- (tee_local $13
- (i32.const 9)
- )
- (if (result i32)
- (i32.and
- (i32.eq
- (get_local $10)
- (i32.const -2147483648)
- )
- (i32.eq
- (get_local $13)
- (i32.const -1)
- )
+ (i32.and
+ (i32.eq
+ (get_local $11)
+ (i32.const -2147483648)
)
(i32.const 0)
- (i32.div_s
- (get_local $10)
- (get_local $13)
- )
)
(i32.const 0)
+ (i32.div_s
+ (get_local $11)
+ (i32.const 9)
+ )
)
)
(if
(i32.lt_s
(tee_local $6
(i32.add
- (if (result i32)
- (tee_local $10
- (i32.const 9)
- )
- (i32.rem_s
- (get_local $6)
- (get_local $10)
- )
- (i32.const 0)
+ (i32.rem_s
+ (get_local $6)
+ (i32.const 9)
)
(i32.const 1)
)
@@ -5205,13 +5174,13 @@
(i32.const 9)
)
(block
- (set_local $10
+ (set_local $11
(i32.const 10)
)
(loop $while-in80
- (set_local $10
+ (set_local $11
(i32.mul
- (get_local $10)
+ (get_local $11)
(i32.const 10)
)
)
@@ -5228,7 +5197,7 @@
)
)
)
- (set_local $10
+ (set_local $11
(i32.const 10)
)
)
@@ -5253,7 +5222,7 @@
(set_local $13
(if (result i32)
(tee_local $13
- (get_local $10)
+ (get_local $11)
)
(i32.rem_u
(get_local $23)
@@ -5266,7 +5235,7 @@
(if
(i32.eqz
(i32.and
- (tee_local $35
+ (tee_local $34
(i32.eq
(i32.add
(get_local $6)
@@ -5284,14 +5253,14 @@
(set_local $23
(get_local $25)
)
- (set_local $30
+ (set_local $35
(if (result i32)
- (tee_local $30
- (get_local $10)
+ (tee_local $35
+ (get_local $11)
)
(i32.div_u
(get_local $23)
- (get_local $30)
+ (get_local $35)
)
(i32.const 0)
)
@@ -5300,33 +5269,24 @@
(if (result f64)
(block (result i32)
(set_local $23
- (get_local $10)
+ (get_local $11)
)
(i32.lt_u
(get_local $13)
(tee_local $23
(if (result i32)
- (tee_local $46
- (i32.const 2)
- )
- (if (result i32)
- (i32.and
- (i32.eq
- (get_local $23)
- (i32.const -2147483648)
- )
- (i32.eq
- (get_local $46)
- (i32.const -1)
- )
- )
- (i32.const 0)
- (i32.div_s
+ (i32.and
+ (i32.eq
(get_local $23)
- (get_local $46)
+ (i32.const -2147483648)
)
+ (i32.const 0)
)
(i32.const 0)
+ (i32.div_s
+ (get_local $23)
+ (i32.const 2)
+ )
)
)
)
@@ -5336,7 +5296,7 @@
(f64.const 1)
(f64.const 1.5)
(i32.and
- (get_local $35)
+ (get_local $34)
(i32.eq
(get_local $13)
(get_local $23)
@@ -5350,7 +5310,7 @@
(f64.const 9007199254740994)
(f64.const 9007199254740992)
(i32.and
- (get_local $30)
+ (get_local $35)
(i32.const 1)
)
)
@@ -5362,7 +5322,7 @@
(br_if $do-once83
(i32.ne
(i32.load8_s
- (get_local $33)
+ (get_local $32)
)
(i32.const 45)
)
@@ -5403,7 +5363,7 @@
(tee_local $7
(i32.add
(get_local $13)
- (get_local $10)
+ (get_local $11)
)
)
)
@@ -5478,7 +5438,7 @@
(i32.const 10)
)
)
- (set_local $10
+ (set_local $11
(i32.const 10)
)
(loop $while-in88
@@ -5491,9 +5451,9 @@
(br_if $while-in88
(i32.ge_u
(get_local $13)
- (tee_local $10
+ (tee_local $11
(i32.mul
- (get_local $10)
+ (get_local $11)
(i32.const 10)
)
)
@@ -5503,7 +5463,7 @@
)
)
)
- (set_local $10
+ (set_local $11
(get_local $5)
)
(set_local $13
@@ -5524,7 +5484,7 @@
)
)
(block (result i32)
- (set_local $10
+ (set_local $11
(get_local $5)
)
(set_local $13
@@ -5534,7 +5494,7 @@
)
)
)
- (set_local $35
+ (set_local $34
(i32.sub
(i32.const 0)
(get_local $13)
@@ -5545,7 +5505,7 @@
(if
(i32.le_u
(get_local $5)
- (get_local $10)
+ (get_local $11)
)
(block
(set_local $25
@@ -5607,7 +5567,7 @@
(tee_local $5
(i32.add
(i32.xor
- (get_local $34)
+ (get_local $33)
(i32.const 1)
)
(get_local $17)
@@ -5692,15 +5652,9 @@
(set_local $5
(get_local $18)
)
- (if (result i32)
- (tee_local $6
- (i32.const 10)
- )
- (i32.rem_u
- (get_local $5)
- (get_local $6)
- )
- (i32.const 0)
+ (i32.rem_u
+ (get_local $5)
+ (i32.const 10)
)
)
(block
@@ -5731,7 +5685,7 @@
(br_if $while-in96
(i32.eqz
(if (result i32)
- (tee_local $30
+ (tee_local $35
(tee_local $6
(i32.mul
(get_local $6)
@@ -5741,7 +5695,7 @@
)
(i32.rem_u
(get_local $23)
- (get_local $30)
+ (get_local $35)
)
(i32.const 0)
)
@@ -5853,7 +5807,7 @@
)
)
(i32.ne
- (tee_local $34
+ (tee_local $33
(i32.or
(get_local $5)
(get_local $21)
@@ -5894,7 +5848,7 @@
(call $_fmt_u
(tee_local $6
(select
- (get_local $35)
+ (get_local $34)
(get_local $13)
(i32.lt_s
(get_local $13)
@@ -5988,7 +5942,7 @@
)
(drop
(call $___fwritex
- (get_local $33)
+ (get_local $32)
(get_local $28)
(get_local $0)
)
@@ -6009,12 +5963,12 @@
(get_local $17)
(block
(set_local $6
- (tee_local $10
+ (tee_local $11
(select
(get_local $8)
- (get_local $10)
+ (get_local $11)
(i32.gt_u
- (get_local $10)
+ (get_local $11)
(get_local $8)
)
)
@@ -6027,20 +5981,20 @@
(get_local $6)
)
(i32.const 0)
- (get_local $32)
+ (get_local $31)
)
)
(block $do-once103
(if
(i32.eq
(get_local $6)
- (get_local $10)
+ (get_local $11)
)
(block
(br_if $do-once103
(i32.ne
(get_local $7)
- (get_local $32)
+ (get_local $31)
)
)
(i32.store8
@@ -6118,7 +6072,7 @@
)
(block $do-once107
(if
- (get_local $34)
+ (get_local $33)
(block
(br_if $do-once107
(i32.and
@@ -6158,7 +6112,7 @@
(get_local $7)
)
(i32.const 0)
- (get_local $32)
+ (get_local $31)
)
)
(get_local $24)
@@ -6255,7 +6209,7 @@
(select
(get_local $9)
(i32.add
- (get_local $10)
+ (get_local $11)
(i32.const 4)
)
(get_local $25)
@@ -6273,7 +6227,7 @@
)
)
(set_local $6
- (get_local $10)
+ (get_local $11)
)
(set_local $7
(get_local $5)
@@ -6287,10 +6241,10 @@
(get_local $6)
)
(i32.const 0)
- (get_local $32)
+ (get_local $31)
)
)
- (get_local $32)
+ (get_local $31)
)
(block
(i32.store8
@@ -6306,7 +6260,7 @@
(if
(i32.eq
(get_local $6)
- (get_local $10)
+ (get_local $11)
)
(block
(if
@@ -6533,7 +6487,7 @@
(block
(drop
(call $___fwritex
- (get_local $33)
+ (get_local $32)
(get_local $9)
(get_local $0)
)
@@ -6606,9 +6560,9 @@
)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $7)
)
(br $label$continue$L1)
@@ -6616,7 +6570,7 @@
(set_local $7
(get_local $5)
)
- (set_local $10
+ (set_local $11
(get_local $6)
)
(set_local $8
@@ -6795,7 +6749,7 @@
(set_local $12
(get_local $8)
)
- (set_local $10
+ (set_local $11
(select
(get_local $6)
(i32.sub
@@ -7001,9 +6955,9 @@
)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(select
(get_local $14)
(get_local $7)
@@ -7028,11 +6982,11 @@
)
)
)
- (set_local $10
+ (set_local $11
(if (result i32)
(i32.or
(get_local $6)
- (tee_local $10
+ (tee_local $11
(i32.or
(i32.ne
(i32.load
@@ -7061,7 +7015,7 @@
(i32.add
(i32.xor
(i32.and
- (get_local $10)
+ (get_local $11)
(i32.const 1)
)
(i32.const 1)
@@ -7097,7 +7051,7 @@
(tee_local $5
(i32.add
(get_local $8)
- (tee_local $10
+ (tee_local $11
(select
(tee_local $13
(i32.sub
@@ -7105,9 +7059,9 @@
(get_local $7)
)
)
- (get_local $10)
+ (get_local $11)
(i32.lt_s
- (get_local $10)
+ (get_local $11)
(get_local $13)
)
)
@@ -7154,7 +7108,7 @@
(call $_pad
(get_local $0)
(i32.const 48)
- (get_local $10)
+ (get_local $11)
(get_local $13)
(i32.const 0)
)
@@ -7186,9 +7140,9 @@
)
)
(set_local $5
- (get_local $11)
+ (get_local $10)
)
- (set_local $11
+ (set_local $10
(get_local $6)
)
(br $label$continue$L1)
@@ -7797,15 +7751,9 @@
)
)
(i32.or
- (if (result i32)
- (tee_local $3
- (i32.const 10)
- )
- (i32.rem_u
- (get_local $1)
- (get_local $3)
- )
- (i32.const 0)
+ (i32.rem_u
+ (get_local $1)
+ (i32.const 10)
)
(i32.const 48)
)
@@ -7814,15 +7762,9 @@
(get_local $0)
)
(set_local $1
- (if (result i32)
- (tee_local $3
- (i32.const 10)
- )
- (i32.div_u
- (get_local $1)
- (get_local $3)
- )
- (i32.const 0)
+ (i32.div_u
+ (get_local $1)
+ (i32.const 10)
)
)
(if
diff --git a/test/passes/precompute-propagate.txt b/test/passes/precompute-propagate.txt
new file mode 100644
index 000000000..90b01be14
--- /dev/null
+++ b/test/passes/precompute-propagate.txt
@@ -0,0 +1,214 @@
+(module
+ (type $0 (func (param i32)))
+ (type $1 (func (param i32) (result i32)))
+ (memory $0 0)
+ (func $basic (type $0) (param $p i32)
+ (local $x i32)
+ (set_local $x
+ (i32.const 10)
+ )
+ (call $basic
+ (i32.const 20)
+ )
+ )
+ (func $split (type $0) (param $p i32)
+ (local $x i32)
+ (if
+ (i32.const 1)
+ (set_local $x
+ (i32.const 10)
+ )
+ )
+ (call $basic
+ (i32.add
+ (get_local $x)
+ (get_local $x)
+ )
+ )
+ )
+ (func $split-but-join (type $0) (param $p i32)
+ (local $x i32)
+ (if
+ (i32.const 1)
+ (set_local $x
+ (i32.const 10)
+ )
+ (set_local $x
+ (i32.const 10)
+ )
+ )
+ (call $basic
+ (i32.const 20)
+ )
+ )
+ (func $split-but-join-different (type $0) (param $p i32)
+ (local $x i32)
+ (if
+ (i32.const 1)
+ (set_local $x
+ (i32.const 10)
+ )
+ (set_local $x
+ (i32.const 20)
+ )
+ )
+ (call $basic
+ (i32.add
+ (get_local $x)
+ (get_local $x)
+ )
+ )
+ )
+ (func $split-but-join-different-b (type $0) (param $p i32)
+ (local $x i32)
+ (if
+ (i32.const 1)
+ (set_local $x
+ (i32.const 10)
+ )
+ (set_local $x
+ (get_local $p)
+ )
+ )
+ (call $basic
+ (i32.add
+ (get_local $x)
+ (get_local $x)
+ )
+ )
+ )
+ (func $split-but-join-init0 (type $0) (param $p i32)
+ (local $x i32)
+ (if
+ (i32.const 1)
+ (set_local $x
+ (i32.const 0)
+ )
+ )
+ (call $basic
+ (i32.const 0)
+ )
+ )
+ (func $later (type $0) (param $p i32)
+ (local $x i32)
+ (set_local $x
+ (i32.const 10)
+ )
+ (call $basic
+ (i32.const 20)
+ )
+ (set_local $x
+ (i32.const 22)
+ )
+ (call $basic
+ (i32.const 44)
+ )
+ (set_local $x
+ (i32.const 39)
+ )
+ )
+ (func $later2 (type $1) (param $p i32) (result i32)
+ (local $x i32)
+ (set_local $x
+ (i32.const 10)
+ )
+ (set_local $x
+ (i32.const 20)
+ )
+ (i32.const 20)
+ )
+ (func $two-ways-but-identical (type $1) (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (set_local $x
+ (i32.const 10)
+ )
+ (if
+ (i32.const 1)
+ (set_local $y
+ (i32.const 11)
+ )
+ (set_local $y
+ (i32.const 11)
+ )
+ )
+ (set_local $y
+ (i32.const 21)
+ )
+ (i32.const 21)
+ )
+ (func $two-ways-but-almost-identical (type $1) (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (set_local $x
+ (i32.const 10)
+ )
+ (if
+ (i32.const 1)
+ (set_local $y
+ (i32.const 12)
+ )
+ (set_local $y
+ (i32.const 11)
+ )
+ )
+ (set_local $y
+ (i32.add
+ (i32.const 10)
+ (get_local $y)
+ )
+ )
+ (get_local $y)
+ )
+ (func $deadloop (type $1) (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop
+ (set_local $x
+ (i32.const 0)
+ )
+ (set_local $y
+ (i32.const 0)
+ )
+ (br $loop)
+ )
+ )
+ (func $deadloop2 (type $0) (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop
+ (set_local $x
+ (i32.const 0)
+ )
+ (set_local $y
+ (i32.const 0)
+ )
+ (call $deadloop2
+ (i32.const 0)
+ )
+ (call $deadloop2
+ (i32.const 0)
+ )
+ (br $loop)
+ )
+ )
+ (func $deadloop3 (type $0) (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop
+ (set_local $x
+ (i32.const 0)
+ )
+ (set_local $y
+ (i32.const 0)
+ )
+ (call $deadloop2
+ (i32.const 0)
+ )
+ (call $deadloop2
+ (i32.const 0)
+ )
+ (br $loop)
+ )
+ )
+)
diff --git a/test/passes/precompute-propagate.wast b/test/passes/precompute-propagate.wast
new file mode 100644
index 000000000..af1a21ba2
--- /dev/null
+++ b/test/passes/precompute-propagate.wast
@@ -0,0 +1,113 @@
+(module
+ (func $basic (param $p i32)
+ (local $x i32)
+ (set_local $x (i32.const 10))
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $split (param $p i32)
+ (local $x i32)
+ (if (i32.const 1)
+ (set_local $x (i32.const 10))
+ )
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $split-but-join (param $p i32)
+ (local $x i32)
+ (if (i32.const 1)
+ (set_local $x (i32.const 10))
+ (set_local $x (i32.const 10))
+ )
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $split-but-join-different (param $p i32)
+ (local $x i32)
+ (if (i32.const 1)
+ (set_local $x (i32.const 10))
+ (set_local $x (i32.const 20))
+ )
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $split-but-join-different-b (param $p i32)
+ (local $x i32)
+ (if (i32.const 1)
+ (set_local $x (i32.const 10))
+ (set_local $x (get_local $p))
+ )
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $split-but-join-init0 (param $p i32)
+ (local $x i32)
+ (if (i32.const 1)
+ (set_local $x (i32.const 0))
+ )
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ )
+ (func $later (param $p i32)
+ (local $x i32)
+ (set_local $x (i32.const 10))
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ (set_local $x (i32.const 22))
+ (call $basic (i32.add (get_local $x) (get_local $x)))
+ (set_local $x (i32.const 39))
+ )
+ (func $later2 (param $p i32) (result i32)
+ (local $x i32)
+ (set_local $x (i32.const 10))
+ (set_local $x (i32.add (get_local $x) (get_local $x)))
+ (get_local $x)
+ )
+ (func $two-ways-but-identical (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (set_local $x (i32.const 10))
+ (if (i32.const 1)
+ (set_local $y (i32.const 11))
+ (set_local $y (i32.add (get_local $x) (i32.const 1)))
+ )
+ (set_local $y (i32.add (get_local $x) (get_local $y)))
+ (get_local $y)
+ )
+ (func $two-ways-but-almost-identical (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (set_local $x (i32.const 10))
+ (if (i32.const 1)
+ (set_local $y (i32.const 12)) ;; 12, not 11...
+ (set_local $y (i32.add (get_local $x) (i32.const 1)))
+ )
+ (set_local $y (i32.add (get_local $x) (get_local $y)))
+ (get_local $y)
+ )
+ (func $deadloop (param $p i32) (result i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop ;; we look like we depend on the other, but we don't actually
+ (set_local $x (if (result i32) (i32.const 1) (i32.const 0) (get_local $y)))
+ (set_local $y (if (result i32) (i32.const 1) (i32.const 0) (get_local $x)))
+ (br $loop)
+ )
+ )
+ (func $deadloop2 (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop ;; we look like we depend on the other, but we don't actually
+ (set_local $x (if (result i32) (i32.const 1) (i32.const 0) (get_local $y)))
+ (set_local $y (if (result i32) (i32.const 1) (i32.const 0) (get_local $x)))
+ (call $deadloop2 (get_local $x))
+ (call $deadloop2 (get_local $y))
+ (br $loop)
+ )
+ )
+ (func $deadloop3 (param $p i32)
+ (local $x i32)
+ (local $y i32)
+ (loop $loop ;; we look like we depend on the other, but we don't actually
+ (set_local $x (if (result i32) (i32.const 1) (i32.const 0) (get_local $x)))
+ (set_local $y (if (result i32) (i32.const 1) (i32.const 0) (get_local $y)))
+ (call $deadloop2 (get_local $x))
+ (call $deadloop2 (get_local $y))
+ (br $loop)
+ )
+ )
+)
+
diff --git a/test/unit.asm.js b/test/unit.asm.js
index a1accabf5..ca7ac90e9 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -51,21 +51,25 @@ function asm(global, env, buffer) {
var t = 0.0;
var Int = 0.0, Double = 0; // confusing with globals
if (x > 0.0) return 1.2;
+ Int = x;
+ Double = n;
if (Int > 0.0) return -3.4;
if ((Double|0) > 0) return 5.6;
if (x < y) return +x;
return +y;
}
- function intOps() {
- var x = 0;
+ function intOps(x) {
+ x = x | 0;
return (!x) | 0;
}
function hexLiterals() {
var i = 0;
i = 0x0 + 0x12ABCdef + 0xFEDcba90 | 0;
}
- function conversions() {
- var i = 0, d = 0.0, f = Math_fround(0);
+ function conversions(i, d, f) {
+ i = i | 0;
+ d = +d;
+ f = Math_fround(f);
i = ~~d;
i = ~~f;
d = +(i | 0);
@@ -185,8 +189,9 @@ function asm(global, env, buffer) {
var $0 = 0;
($0>>>0) > 4294963200; // -4096
}
- function smallCompare() {
- var i = 0, j = 0;
+ function smallCompare(i, j) {
+ i = i | 0;
+ j = j | 0;
if ((i | 0) < (j | 0)) i = i + 1 | 0;
if ((i >>> 0) < (j >>> 0)) i = i + 1 | 0;
return i | 0;
@@ -432,6 +437,30 @@ function asm(global, env, buffer) {
return i$lcssa | 0
}
+ function loophi2b() {
+ var jnc = 0, i = 0, i$lcssa = 0, temp = 0, j = 0;
+ i = 0;
+ L7: while(1) {
+ j = 0;
+ while(1) {
+ temp = j;
+ if (return_int() | 0) {
+ if (temp) {
+ i$lcssa = j;
+ break L7;
+ }
+ }
+ jnc = j + 1 | 0;
+ if (jnc) {
+ j = jnc;
+ } else {
+ break;
+ }
+ }
+ }
+ return i$lcssa | 0
+ }
+
function relooperJumpThreading(x) {
x = x | 0;
var label = 0;
@@ -530,8 +559,15 @@ function asm(global, env, buffer) {
return x | 0;
}
- function relooperJumpThreading__ZN4game14preloadweaponsEv() {
- var $12 = 0, $14 = 0, $or$cond8 = 0, $or$cond6 = 0, $vararg_ptr5 = 0, $11 = 0, $exitcond = 0, label = 0;
+ function relooperJumpThreading__ZN4game14preloadweaponsEv($12, $14, $or$cond8, $or$cond6, $vararg_ptr5, $11, $exitcond) {
+ $12 = $12 | 0;
+ $14 = $14 | 0;
+ $or$cond8 = $or$cond8 | 0;
+ $or$cond6 = $or$cond6 | 0;
+ $vararg_ptr5 = $vararg_ptr5 | 0;
+ $11 = $11 | 0;
+ $exitcond = $exitcond | 0;
+ var label = 0;
while(1) {
if ($14) {
if ($or$cond8) {
@@ -587,9 +623,12 @@ function asm(global, env, buffer) {
}
}
- function __Z12multi_varargiz($0) {
+ function __Z12multi_varargiz($0, $$06$i4, $exitcond$i6, $2) {
$0 = $0|0;
- var $2 = 0, $$06$i4 = 0, $exitcond$i6 = 0, $12 = 0, $20 = 0;
+ $$06$i4 = $$06$i4 | 0;
+ $exitcond$i6 = $exitcond$i6 | 0;
+ $2 = $2 | 0;
+ var $12 = 0, $20 = 0;
if ($2) {
while(1) {
$12 = $$06$i4;
@@ -751,6 +790,6 @@ function asm(global, env, buffer) {
var FUNCTION_TABLE_vi = [ vi, vi, vi, vi, vi, vi, vi, vi ];
var FUNCTION_TABLE_ii = [ ii ];
- return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, frem_float: frem_float, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42, relocatableAndModules: relocatableAndModules, exported_f32_user: exported_f32_user, keepAlive: keepAlive };
+ return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, frem_float: frem_float, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, loophi2b: loophi2b, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42, relocatableAndModules: relocatableAndModules, exported_f32_user: exported_f32_user, keepAlive: keepAlive };
}
diff --git a/test/unit.fromasm b/test/unit.fromasm
index ec97a3320..1588f651b 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -31,7 +31,7 @@
(export "pick" (func $big_negative))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $conversions))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -63,6 +63,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -100,8 +101,6 @@
(f64.const 1.2)
)
(func $doubleCompares (param $0 f64) (param $1 f64) (result f64)
- (local $2 f64)
- (local $3 i32)
(if
(f64.gt
(get_local $0)
@@ -113,7 +112,7 @@
)
(if
(f64.gt
- (get_local $2)
+ (get_local $0)
(f64.const 0)
)
(return
@@ -122,7 +121,7 @@
)
(if
(i32.gt_s
- (get_local $3)
+ (get_global $n)
(i32.const 0)
)
(return
@@ -140,24 +139,21 @@
)
(get_local $1)
)
- (func $intOps (result i32)
- (local $0 i32)
+ (func $intOps (param $0 i32) (result i32)
(i32.eqz
(get_local $0)
)
)
- (func $conversions
- (local $0 f64)
- (local $1 f32)
+ (func $conversions (param $0 i32) (param $1 f64) (param $2 f32)
(drop
(call $f64-to-int
- (get_local $0)
+ (get_local $1)
)
)
(drop
(call $f64-to-int
(f64.promote/f32
- (get_local $1)
+ (get_local $2)
)
)
)
@@ -256,21 +252,7 @@
)
)
(func $big_uint_div_u (result i32)
- (local $0 i32)
- (local $1 i32)
- (set_local $0
- (i32.const -1)
- )
- (if (result i32)
- (tee_local $1
- (i32.const 2)
- )
- (i32.div_u
- (get_local $0)
- (get_local $1)
- )
- (i32.const 0)
- )
+ (i32.const 2147483647)
)
(func $fr (param $0 f32)
(nop)
@@ -293,9 +275,7 @@
(i32.const 9)
)
)
- (func $smallCompare (result i32)
- (local $0 i32)
- (local $1 i32)
+ (func $smallCompare (param $0 i32) (param $1 i32) (result i32)
(if
(i32.lt_s
(get_local $0)
@@ -819,6 +799,38 @@
)
(get_local $1)
)
+ (func $loophi2b (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $0
+ (i32.const 0)
+ )
+ (loop $while-in
+ (set_local $1
+ (get_local $0)
+ )
+ (if
+ (call $return_int)
+ (br_if $label$break$L7
+ (get_local $1)
+ )
+ )
+ (br_if $while-in
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (get_local $0)
+ )
(func $relooperJumpThreading (param $0 i32) (result i32)
(block $__rjto$0
(block $__rjti$0
@@ -988,33 +1000,28 @@
)
(get_local $0)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $0 i32)
- (local $1 i32)
- (local $2 i32)
- (local $3 i32)
- (local $4 i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32)
(loop $while-in
(block $__rjto$1
(block $__rjti$1
(if
- (get_local $0)
+ (get_local $1)
(br_if $__rjti$1
(i32.eqz
- (get_local $1)
+ (get_local $2)
)
)
(br_if $__rjti$1
(i32.eqz
- (get_local $2)
+ (get_local $3)
)
)
)
(br $while-in)
)
(i32.store
- (get_local $3)
(get_local $4)
+ (get_local $5)
)
)
(br $while-in)
@@ -1072,11 +1079,9 @@
)
)
)
- (func $__Z12multi_varargiz (param $0 i32)
- (local $1 i32)
- (local $2 i32)
+ (func $__Z12multi_varargiz (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
- (get_local $1)
+ (get_local $3)
(loop $while-in
(br_if $while-in
(i32.eqz
@@ -1163,7 +1168,6 @@
)
)
(func $keepAlive
- (local $0 i32)
(drop
(call $sqrts
(f64.const 3.14159)
@@ -1184,24 +1188,12 @@
(f64.const 100)
)
)
- (block $__inlined_func$autoDrop
- (br_if $__inlined_func$autoDrop
- (i32.eq
- (tee_local $0
- (i32.const 52)
- )
- (i32.const 17)
- )
- )
- )
(call_indirect $FUNCSIG$vi
(i32.const 0)
(i32.const 17)
)
(call_indirect $FUNCSIG$vi
- (tee_local $0
- (i32.const 0)
- )
+ (i32.const 0)
(block (result i32)
(set_global $Int
(i32.const 1)
@@ -1230,6 +1222,15 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp
index b110204f9..4393c362c 100644
--- a/test/unit.fromasm.clamp
+++ b/test/unit.fromasm.clamp
@@ -29,7 +29,7 @@
(export "pick" (func $big_negative))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $conversions))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -61,6 +61,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -98,8 +99,6 @@
(f64.const 1.2)
)
(func $doubleCompares (param $0 f64) (param $1 f64) (result f64)
- (local $2 f64)
- (local $3 i32)
(if
(f64.gt
(get_local $0)
@@ -111,7 +110,7 @@
)
(if
(f64.gt
- (get_local $2)
+ (get_local $0)
(f64.const 0)
)
(return
@@ -120,7 +119,7 @@
)
(if
(i32.gt_s
- (get_local $3)
+ (get_global $n)
(i32.const 0)
)
(return
@@ -138,8 +137,7 @@
)
(get_local $1)
)
- (func $intOps (result i32)
- (local $0 i32)
+ (func $intOps (param $0 i32) (result i32)
(i32.eqz
(get_local $0)
)
@@ -170,18 +168,16 @@
)
)
)
- (func $conversions
- (local $0 f64)
- (local $1 f32)
+ (func $conversions (param $0 i32) (param $1 f64) (param $2 f32)
(drop
(call $f64-to-int
- (get_local $0)
+ (get_local $1)
)
)
(drop
(call $f64-to-int
(f64.promote/f32
- (get_local $1)
+ (get_local $2)
)
)
)
@@ -280,21 +276,7 @@
)
)
(func $big_uint_div_u (result i32)
- (local $0 i32)
- (local $1 i32)
- (set_local $0
- (i32.const -1)
- )
- (if (result i32)
- (tee_local $1
- (i32.const 2)
- )
- (i32.div_u
- (get_local $0)
- (get_local $1)
- )
- (i32.const 0)
- )
+ (i32.const 2147483647)
)
(func $fr (param $0 f32)
(nop)
@@ -317,9 +299,7 @@
(i32.const 9)
)
)
- (func $smallCompare (result i32)
- (local $0 i32)
- (local $1 i32)
+ (func $smallCompare (param $0 i32) (param $1 i32) (result i32)
(if
(i32.lt_s
(get_local $0)
@@ -843,6 +823,38 @@
)
(get_local $1)
)
+ (func $loophi2b (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $0
+ (i32.const 0)
+ )
+ (loop $while-in
+ (set_local $1
+ (get_local $0)
+ )
+ (if
+ (call $return_int)
+ (br_if $label$break$L7
+ (get_local $1)
+ )
+ )
+ (br_if $while-in
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (get_local $0)
+ )
(func $relooperJumpThreading (param $0 i32) (result i32)
(block $__rjto$0
(block $__rjti$0
@@ -1012,33 +1024,28 @@
)
(get_local $0)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $0 i32)
- (local $1 i32)
- (local $2 i32)
- (local $3 i32)
- (local $4 i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32)
(loop $while-in
(block $__rjto$1
(block $__rjti$1
(if
- (get_local $0)
+ (get_local $1)
(br_if $__rjti$1
(i32.eqz
- (get_local $1)
+ (get_local $2)
)
)
(br_if $__rjti$1
(i32.eqz
- (get_local $2)
+ (get_local $3)
)
)
)
(br $while-in)
)
(i32.store
- (get_local $3)
(get_local $4)
+ (get_local $5)
)
)
(br $while-in)
@@ -1096,11 +1103,9 @@
)
)
)
- (func $__Z12multi_varargiz (param $0 i32)
- (local $1 i32)
- (local $2 i32)
+ (func $__Z12multi_varargiz (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
- (get_local $1)
+ (get_local $3)
(loop $while-in
(br_if $while-in
(i32.eqz
@@ -1187,7 +1192,6 @@
)
)
(func $keepAlive
- (local $0 i32)
(drop
(call $sqrts
(f64.const 3.14159)
@@ -1208,24 +1212,12 @@
(f64.const 100)
)
)
- (block $__inlined_func$autoDrop
- (br_if $__inlined_func$autoDrop
- (i32.eq
- (tee_local $0
- (i32.const 52)
- )
- (i32.const 17)
- )
- )
- )
(call_indirect $FUNCSIG$vi
(i32.const 0)
(i32.const 17)
)
(call_indirect $FUNCSIG$vi
- (tee_local $0
- (i32.const 0)
- )
+ (i32.const 0)
(block (result i32)
(set_global $Int
(i32.const 1)
@@ -1254,6 +1246,15 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/unit.fromasm.clamp.no-opts b/test/unit.fromasm.clamp.no-opts
index f4fe4bf83..00b1814c4 100644
--- a/test/unit.fromasm.clamp.no-opts
+++ b/test/unit.fromasm.clamp.no-opts
@@ -36,7 +36,7 @@
(export "pick" (func $exportMe))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $conversions))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -68,6 +68,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -151,6 +152,12 @@
(f64.const 1.2)
)
)
+ (set_local $Int
+ (get_local $x)
+ )
+ (set_local $Double
+ (get_global $n)
+ )
(if
(f64.gt
(get_local $Int)
@@ -182,8 +189,7 @@
(get_local $y)
)
)
- (func $intOps (result i32)
- (local $x i32)
+ (func $intOps (param $x i32) (result i32)
(return
(i32.eqz
(get_local $x)
@@ -228,10 +234,7 @@
)
)
)
- (func $conversions
- (local $i i32)
- (local $d f64)
- (local $f f32)
+ (func $conversions (param $i i32) (param $d f64) (param $f f32)
(set_local $i
(call $f64-to-int
(get_local $d)
@@ -582,9 +585,7 @@
)
)
)
- (func $smallCompare (result i32)
- (local $i i32)
- (local $j i32)
+ (func $smallCompare (param $i i32) (param $j i32) (result i32)
(if
(i32.lt_s
(get_local $i)
@@ -1381,6 +1382,60 @@
(get_local $i$lcssa)
)
)
+ (func $loophi2b (result i32)
+ (local $jnc i32)
+ (local $i i32)
+ (local $i$lcssa i32)
+ (local $temp i32)
+ (local $j i32)
+ (set_local $i
+ (i32.const 0)
+ )
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $j
+ (i32.const 0)
+ )
+ (loop $while-in
+ (block $while-out
+ (set_local $temp
+ (get_local $j)
+ )
+ (if
+ (call $return_int)
+ (if
+ (get_local $temp)
+ (block
+ (set_local $i$lcssa
+ (get_local $j)
+ )
+ (br $label$break$L7)
+ )
+ )
+ )
+ (set_local $jnc
+ (i32.add
+ (get_local $j)
+ (i32.const 1)
+ )
+ )
+ (if
+ (get_local $jnc)
+ (set_local $j
+ (get_local $jnc)
+ )
+ (br $while-out)
+ )
+ (br $while-in)
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (return
+ (get_local $i$lcssa)
+ )
+ )
(func $relooperJumpThreading (param $x i32) (result i32)
(local $label i32)
(if
@@ -1620,14 +1675,7 @@
(get_local $x)
)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $$12 i32)
- (local $$14 i32)
- (local $$or$cond8 i32)
- (local $$or$cond6 i32)
- (local $$vararg_ptr5 i32)
- (local $$11 i32)
- (local $$exitcond i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $$12 i32) (param $$14 i32) (param $$or$cond8 i32) (param $$or$cond6 i32) (param $$vararg_ptr5 i32) (param $$11 i32) (param $$exitcond i32)
(local $label i32)
(loop $while-in
(block $while-out
@@ -1751,10 +1799,7 @@
)
)
)
- (func $__Z12multi_varargiz (param $$0 i32)
- (local $$2 i32)
- (local $$$06$i4 i32)
- (local $$exitcond$i6 i32)
+ (func $__Z12multi_varargiz (param $$0 i32) (param $$$06$i4 i32) (param $$exitcond$i6 i32) (param $$2 i32)
(local $$12 i32)
(local $$20 i32)
(if
@@ -2068,6 +2113,15 @@
(get_local $x)
)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index 13c29f151..fec7e2038 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -28,7 +28,7 @@
(export "pick" (func $big_negative))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $big_negative))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -60,6 +60,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -97,8 +98,6 @@
(f64.const 1.2)
)
(func $doubleCompares (param $0 f64) (param $1 f64) (result f64)
- (local $2 f64)
- (local $3 i32)
(if
(f64.gt
(get_local $0)
@@ -110,7 +109,7 @@
)
(if
(f64.gt
- (get_local $2)
+ (get_local $0)
(f64.const 0)
)
(return
@@ -119,7 +118,7 @@
)
(if
(i32.gt_s
- (get_local $3)
+ (get_global $n)
(i32.const 0)
)
(return
@@ -137,12 +136,14 @@
)
(get_local $1)
)
- (func $intOps (result i32)
- (local $0 i32)
+ (func $intOps (param $0 i32) (result i32)
(i32.eqz
(get_local $0)
)
)
+ (func $conversions (param $0 i32) (param $1 f64) (param $2 f32)
+ (nop)
+ )
(func $switcher (param $0 i32) (result i32)
(block $switch
(block $switch-case0
@@ -260,9 +261,7 @@
(i32.const 9)
)
)
- (func $smallCompare (result i32)
- (local $0 i32)
- (local $1 i32)
+ (func $smallCompare (param $0 i32) (param $1 i32) (result i32)
(if
(i32.lt_s
(get_local $0)
@@ -786,6 +785,38 @@
)
(get_local $1)
)
+ (func $loophi2b (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $0
+ (i32.const 0)
+ )
+ (loop $while-in
+ (set_local $1
+ (get_local $0)
+ )
+ (if
+ (call $return_int)
+ (br_if $label$break$L7
+ (get_local $1)
+ )
+ )
+ (br_if $while-in
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (get_local $0)
+ )
(func $relooperJumpThreading (param $0 i32) (result i32)
(block $__rjto$0
(block $__rjti$0
@@ -955,33 +986,28 @@
)
(get_local $0)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $0 i32)
- (local $1 i32)
- (local $2 i32)
- (local $3 i32)
- (local $4 i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32)
(loop $while-in
(block $__rjto$1
(block $__rjti$1
(if
- (get_local $0)
+ (get_local $1)
(br_if $__rjti$1
(i32.eqz
- (get_local $1)
+ (get_local $2)
)
)
(br_if $__rjti$1
(i32.eqz
- (get_local $2)
+ (get_local $3)
)
)
)
(br $while-in)
)
(i32.store
- (get_local $3)
(get_local $4)
+ (get_local $5)
)
)
(br $while-in)
@@ -1039,11 +1065,9 @@
)
)
)
- (func $__Z12multi_varargiz (param $0 i32)
- (local $1 i32)
- (local $2 i32)
+ (func $__Z12multi_varargiz (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
- (get_local $1)
+ (get_local $3)
(loop $while-in
(br_if $while-in
(i32.eqz
@@ -1125,7 +1149,6 @@
)
)
(func $keepAlive
- (local $0 i32)
(drop
(call $sqrts
(f64.const 3.14159)
@@ -1136,24 +1159,12 @@
(f64.const 2.18281)
)
)
- (block $__inlined_func$autoDrop
- (br_if $__inlined_func$autoDrop
- (i32.eq
- (tee_local $0
- (i32.const 52)
- )
- (i32.const 17)
- )
- )
- )
(call_indirect $FUNCSIG$vi
(i32.const 0)
(i32.const 17)
)
(call_indirect $FUNCSIG$vi
- (tee_local $0
- (i32.const 0)
- )
+ (i32.const 0)
(block (result i32)
(set_global $Int
(i32.const 1)
@@ -1182,6 +1193,15 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index 243b8b8fe..76934df4b 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -36,7 +36,7 @@
(export "pick" (func $exportMe))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $conversions))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -68,6 +68,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -151,6 +152,12 @@
(f64.const 1.2)
)
)
+ (set_local $Int
+ (get_local $x)
+ )
+ (set_local $Double
+ (get_global $n)
+ )
(if
(f64.gt
(get_local $Int)
@@ -182,8 +189,7 @@
(get_local $y)
)
)
- (func $intOps (result i32)
- (local $x i32)
+ (func $intOps (param $x i32) (result i32)
(return
(i32.eqz
(get_local $x)
@@ -202,10 +208,7 @@
)
)
)
- (func $conversions
- (local $i i32)
- (local $d f64)
- (local $f f32)
+ (func $conversions (param $i i32) (param $d f64) (param $f f32)
(set_local $i
(i32.trunc_s/f64
(get_local $d)
@@ -542,9 +545,7 @@
)
)
)
- (func $smallCompare (result i32)
- (local $i i32)
- (local $j i32)
+ (func $smallCompare (param $i i32) (param $j i32) (result i32)
(if
(i32.lt_s
(get_local $i)
@@ -1341,6 +1342,60 @@
(get_local $i$lcssa)
)
)
+ (func $loophi2b (result i32)
+ (local $jnc i32)
+ (local $i i32)
+ (local $i$lcssa i32)
+ (local $temp i32)
+ (local $j i32)
+ (set_local $i
+ (i32.const 0)
+ )
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $j
+ (i32.const 0)
+ )
+ (loop $while-in
+ (block $while-out
+ (set_local $temp
+ (get_local $j)
+ )
+ (if
+ (call $return_int)
+ (if
+ (get_local $temp)
+ (block
+ (set_local $i$lcssa
+ (get_local $j)
+ )
+ (br $label$break$L7)
+ )
+ )
+ )
+ (set_local $jnc
+ (i32.add
+ (get_local $j)
+ (i32.const 1)
+ )
+ )
+ (if
+ (get_local $jnc)
+ (set_local $j
+ (get_local $jnc)
+ )
+ (br $while-out)
+ )
+ (br $while-in)
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (return
+ (get_local $i$lcssa)
+ )
+ )
(func $relooperJumpThreading (param $x i32) (result i32)
(local $label i32)
(if
@@ -1580,14 +1635,7 @@
(get_local $x)
)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $$12 i32)
- (local $$14 i32)
- (local $$or$cond8 i32)
- (local $$or$cond6 i32)
- (local $$vararg_ptr5 i32)
- (local $$11 i32)
- (local $$exitcond i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $$12 i32) (param $$14 i32) (param $$or$cond8 i32) (param $$or$cond6 i32) (param $$vararg_ptr5 i32) (param $$11 i32) (param $$exitcond i32)
(local $label i32)
(loop $while-in
(block $while-out
@@ -1711,10 +1759,7 @@
)
)
)
- (func $__Z12multi_varargiz (param $$0 i32)
- (local $$2 i32)
- (local $$$06$i4 i32)
- (local $$exitcond$i6 i32)
+ (func $__Z12multi_varargiz (param $$0 i32) (param $$$06$i4 i32) (param $$exitcond$i6 i32) (param $$2 i32)
(local $$12 i32)
(local $$20 i32)
(if
@@ -2028,6 +2073,15 @@
(get_local $x)
)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 09d8361bd..021ce41f9 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -38,7 +38,7 @@
(export "pick" (func $exportMe))
(export "doubleCompares" (func $doubleCompares))
(export "intOps" (func $intOps))
- (export "conversions" (func $conversions))
+ (export "conversions" (func $legalstub$conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
(export "frem_float" (func $legalstub$frem_float))
@@ -70,6 +70,7 @@
(export "dropCallImport" (func $dropCallImport))
(export "loophi" (func $loophi))
(export "loophi2" (func $loophi2))
+ (export "loophi2b" (func $loophi2b))
(export "relooperJumpThreading" (func $relooperJumpThreading))
(export "relooperJumpThreading__ZN4game14preloadweaponsEv" (func $relooperJumpThreading__ZN4game14preloadweaponsEv))
(export "__Z12multi_varargiz" (func $__Z12multi_varargiz))
@@ -153,6 +154,12 @@
(f64.const 1.2)
)
)
+ (set_local $Int
+ (get_local $x)
+ )
+ (set_local $Double
+ (get_global $n)
+ )
(if
(f64.gt
(get_local $Int)
@@ -184,8 +191,7 @@
(get_local $y)
)
)
- (func $intOps (result i32)
- (local $x i32)
+ (func $intOps (param $x i32) (result i32)
(return
(i32.eqz
(get_local $x)
@@ -204,10 +210,7 @@
)
)
)
- (func $conversions
- (local $i i32)
- (local $d f64)
- (local $f f32)
+ (func $conversions (param $i i32) (param $d f64) (param $f f32)
(set_local $i
(call $f64-to-int
(get_local $d)
@@ -558,9 +561,7 @@
)
)
)
- (func $smallCompare (result i32)
- (local $i i32)
- (local $j i32)
+ (func $smallCompare (param $i i32) (param $j i32) (result i32)
(if
(i32.lt_s
(get_local $i)
@@ -1357,6 +1358,60 @@
(get_local $i$lcssa)
)
)
+ (func $loophi2b (result i32)
+ (local $jnc i32)
+ (local $i i32)
+ (local $i$lcssa i32)
+ (local $temp i32)
+ (local $j i32)
+ (set_local $i
+ (i32.const 0)
+ )
+ (loop $label$continue$L7
+ (block $label$break$L7
+ (set_local $j
+ (i32.const 0)
+ )
+ (loop $while-in
+ (block $while-out
+ (set_local $temp
+ (get_local $j)
+ )
+ (if
+ (call $return_int)
+ (if
+ (get_local $temp)
+ (block
+ (set_local $i$lcssa
+ (get_local $j)
+ )
+ (br $label$break$L7)
+ )
+ )
+ )
+ (set_local $jnc
+ (i32.add
+ (get_local $j)
+ (i32.const 1)
+ )
+ )
+ (if
+ (get_local $jnc)
+ (set_local $j
+ (get_local $jnc)
+ )
+ (br $while-out)
+ )
+ (br $while-in)
+ )
+ )
+ (br $label$continue$L7)
+ )
+ )
+ (return
+ (get_local $i$lcssa)
+ )
+ )
(func $relooperJumpThreading (param $x i32) (result i32)
(local $label i32)
(if
@@ -1596,14 +1651,7 @@
(get_local $x)
)
)
- (func $relooperJumpThreading__ZN4game14preloadweaponsEv
- (local $$12 i32)
- (local $$14 i32)
- (local $$or$cond8 i32)
- (local $$or$cond6 i32)
- (local $$vararg_ptr5 i32)
- (local $$11 i32)
- (local $$exitcond i32)
+ (func $relooperJumpThreading__ZN4game14preloadweaponsEv (param $$12 i32) (param $$14 i32) (param $$or$cond8 i32) (param $$or$cond6 i32) (param $$vararg_ptr5 i32) (param $$11 i32) (param $$exitcond i32)
(local $label i32)
(loop $while-in
(block $while-out
@@ -1727,10 +1775,7 @@
)
)
)
- (func $__Z12multi_varargiz (param $$0 i32)
- (local $$2 i32)
- (local $$$06$i4 i32)
- (local $$exitcond$i6 i32)
+ (func $__Z12multi_varargiz (param $$0 i32) (param $$$06$i4 i32) (param $$exitcond$i6 i32) (param $$2 i32)
(local $$12 i32)
(local $$20 i32)
(if
@@ -2044,6 +2089,15 @@
(get_local $x)
)
)
+ (func $legalstub$conversions (param $0 i32) (param $1 f64) (param $2 f64)
+ (call $conversions
+ (get_local $0)
+ (get_local $1)
+ (f32.demote/f64
+ (get_local $2)
+ )
+ )
+ )
(func $legalstub$frem_float (result f64)
(f64.promote/f32
(call $frem_float)
diff --git a/test/wasm-only.fromasm b/test/wasm-only.fromasm
index 8f9825dda..2ac96b8ae 100644
--- a/test/wasm-only.fromasm
+++ b/test/wasm-only.fromasm
@@ -294,67 +294,41 @@
)
(func $test64
(local $0 i64)
- (local $1 i64)
- (local $2 i64)
- (local $3 f32)
- (local $4 f64)
- (set_local $2
+ (local $1 f32)
+ (local $2 f64)
+ (set_local $0
(call $i64s-div
(block (result i64)
- (set_local $2
+ (set_local $0
(i64.mul
(i64.sub
(i64.add
- (tee_local $0
- (i64.const 128849018897)
- )
+ (i64.const 128849018897)
(i64.const 100)
)
- (get_local $0)
+ (i64.const 128849018897)
)
- (get_local $0)
+ (i64.const 128849018897)
)
)
- (if (result i64)
- (i64.eqz
- (tee_local $1
- (get_local $0)
- )
- )
- (i64.const 0)
- (i64.div_u
- (get_local $2)
- (get_local $1)
- )
+ (i64.div_u
+ (get_local $0)
+ (i64.const 128849018897)
)
)
- (get_local $0)
+ (i64.const 128849018897)
)
)
- (set_local $1
- (if (result i64)
- (i64.eqz
- (tee_local $1
- (get_local $0)
- )
- )
- (i64.const 0)
- (i64.rem_u
- (get_local $2)
- (get_local $1)
- )
+ (set_local $0
+ (i64.rem_u
+ (get_local $0)
+ (i64.const 128849018897)
)
)
(drop
- (if (result i64)
- (i64.eqz
- (get_local $0)
- )
- (i64.const 0)
- (i64.rem_s
- (get_local $1)
- (get_local $0)
- )
+ (i64.rem_s
+ (get_local $0)
+ (i64.const 128849018897)
)
)
(drop
@@ -404,7 +378,7 @@
(drop
(call $f64-to-int64
(f64.promote/f32
- (tee_local $3
+ (tee_local $1
(f32.convert_u/i64
(tee_local $0
(i64.extend_u/i32
@@ -420,7 +394,7 @@
)
(drop
(call $f64-to-int64
- (tee_local $4
+ (tee_local $2
(f64.convert_u/i64
(get_local $0)
)
@@ -430,13 +404,13 @@
(drop
(call $f64-to-int64
(f64.promote/f32
- (get_local $3)
+ (get_local $1)
)
)
)
(drop
(call $f64-to-int64
- (get_local $4)
+ (get_local $2)
)
)
)
diff --git a/test/wasm-only.fromasm.clamp b/test/wasm-only.fromasm.clamp
index 8f9825dda..2ac96b8ae 100644
--- a/test/wasm-only.fromasm.clamp
+++ b/test/wasm-only.fromasm.clamp
@@ -294,67 +294,41 @@
)
(func $test64
(local $0 i64)
- (local $1 i64)
- (local $2 i64)
- (local $3 f32)
- (local $4 f64)
- (set_local $2
+ (local $1 f32)
+ (local $2 f64)
+ (set_local $0
(call $i64s-div
(block (result i64)
- (set_local $2
+ (set_local $0
(i64.mul
(i64.sub
(i64.add
- (tee_local $0
- (i64.const 128849018897)
- )
+ (i64.const 128849018897)
(i64.const 100)
)
- (get_local $0)
+ (i64.const 128849018897)
)
- (get_local $0)
+ (i64.const 128849018897)
)
)
- (if (result i64)
- (i64.eqz
- (tee_local $1
- (get_local $0)
- )
- )
- (i64.const 0)
- (i64.div_u
- (get_local $2)
- (get_local $1)
- )
+ (i64.div_u
+ (get_local $0)
+ (i64.const 128849018897)
)
)
- (get_local $0)
+ (i64.const 128849018897)
)
)
- (set_local $1
- (if (result i64)
- (i64.eqz
- (tee_local $1
- (get_local $0)
- )
- )
- (i64.const 0)
- (i64.rem_u
- (get_local $2)
- (get_local $1)
- )
+ (set_local $0
+ (i64.rem_u
+ (get_local $0)
+ (i64.const 128849018897)
)
)
(drop
- (if (result i64)
- (i64.eqz
- (get_local $0)
- )
- (i64.const 0)
- (i64.rem_s
- (get_local $1)
- (get_local $0)
- )
+ (i64.rem_s
+ (get_local $0)
+ (i64.const 128849018897)
)
)
(drop
@@ -404,7 +378,7 @@
(drop
(call $f64-to-int64
(f64.promote/f32
- (tee_local $3
+ (tee_local $1
(f32.convert_u/i64
(tee_local $0
(i64.extend_u/i32
@@ -420,7 +394,7 @@
)
(drop
(call $f64-to-int64
- (tee_local $4
+ (tee_local $2
(f64.convert_u/i64
(get_local $0)
)
@@ -430,13 +404,13 @@
(drop
(call $f64-to-int64
(f64.promote/f32
- (get_local $3)
+ (get_local $1)
)
)
)
(drop
(call $f64-to-int64
- (get_local $4)
+ (get_local $2)
)
)
)