summaryrefslogtreecommitdiff
path: root/src/passes/Precompute.cpp
diff options
context:
space:
mode:
authorDaniel Wirtz <dcode@dcode.io>2018-07-18 19:16:29 +0200
committerAlon Zakai <alonzakai@gmail.com>2018-07-18 10:16:29 -0700
commit25890f53cba4b9b05341ac146dde755a7fa4fddd (patch)
tree6fe6ca4b9401dc59df1d9b9d2aded6d70005b4df /src/passes/Precompute.cpp
parente601522b1e15e5a2a96578244faca1648021fb2d (diff)
downloadbinaryen-25890f53cba4b9b05341ac146dde755a7fa4fddd.tar.gz
binaryen-25890f53cba4b9b05341ac146dde755a7fa4fddd.tar.bz2
binaryen-25890f53cba4b9b05341ac146dde755a7fa4fddd.zip
Support constant globals in precompute pass (#1622)
This PR includes non-mutable globals in precompute, which will allow me to continue removing manual inlining of constants in AssemblyScript without breaking something. Related: #1621, i.e. enum Animal { CAT = 0, DOG = CAT + 1 // requires that `Animal.CAT` is evaluated to // precompute the constant value for `Animal.DOG` }
Diffstat (limited to 'src/passes/Precompute.cpp')
-rw-r--r--src/passes/Precompute.cpp54
1 files changed, 31 insertions, 23 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index 8d6111ab4..b902c4231 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -29,12 +29,14 @@
namespace wasm {
-static const Name NONSTANDALONE_FLOW("Binaryen|nonstandalone");
+static const Name NOTPRECOMPUTABLE_FLOW("Binaryen|notprecomputable");
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> {
+// Precomputes an expression. Errors if we hit anything that can't be precomputed.
+class PrecomputingExpressionRunner : public ExpressionRunner<PrecomputingExpressionRunner> {
+ Module* module;
+
// map gets to constant values, if they are known to be constant
GetValues& getValues;
@@ -46,24 +48,24 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR
bool replaceExpression;
public:
- StandaloneExpressionRunner(GetValues& getValues, bool replaceExpression) : getValues(getValues), replaceExpression(replaceExpression) {}
+ PrecomputingExpressionRunner(Module* module, GetValues& getValues, bool replaceExpression) : module(module), getValues(getValues), replaceExpression(replaceExpression) {}
struct NonstandaloneException {}; // TODO: use a flow with a special name, as this is likely very slow
Flow visitLoop(Loop* curr) {
// loops might be infinite, so must be careful
// but we can't tell if non-infinite, since we don't have state, so loops are just impossible to optimize for now
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitCall(Call* curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitCallImport(CallImport* curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitCallIndirect(CallIndirect* curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitGetLocal(GetLocal *curr) {
auto iter = getValues.find(curr);
@@ -73,7 +75,7 @@ public:
return Flow(value);
}
}
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitSetLocal(SetLocal *curr) {
// If we don't need to replace the whole expression, see if there
@@ -84,34 +86,40 @@ public:
return visit(curr->value);
}
}
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitGetGlobal(GetGlobal *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ auto* global = module->getGlobalOrNull(curr->name);
+ if (global) {
+ if (!global->mutable_) {
+ return visit(global->init);
+ }
+ }
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitSetGlobal(SetGlobal *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitLoad(Load *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitStore(Store *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitAtomicRMW(AtomicRMW *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitAtomicCmpxchg(AtomicCmpxchg *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitAtomicWait(AtomicWait *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitAtomicWake(AtomicWake *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
Flow visitHost(Host *curr) {
- return Flow(NONSTANDALONE_FLOW);
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
void trap(const char* why) override {
@@ -156,7 +164,7 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi
// try to evaluate this into a const
Flow flow = precomputeExpression(curr);
if (flow.breaking()) {
- if (flow.breakTo == NONSTANDALONE_FLOW) return;
+ if (flow.breakTo == NOTPRECOMPUTABLE_FLOW) return;
if (flow.breakTo == RETURN_FLOW) {
// this expression causes a return. if it's already a return, reuse the node
if (auto* ret = curr->dynCast<Return>()) {
@@ -223,9 +231,9 @@ private:
// (that we can replace the expression with if replaceExpression is set).
Flow precomputeExpression(Expression* curr, bool replaceExpression = true) {
try {
- return StandaloneExpressionRunner(getValues, replaceExpression).visit(curr);
- } catch (StandaloneExpressionRunner::NonstandaloneException&) {
- return Flow(NONSTANDALONE_FLOW);
+ return PrecomputingExpressionRunner(getModule(), getValues, replaceExpression).visit(curr);
+ } catch (PrecomputingExpressionRunner::NonstandaloneException&) {
+ return Flow(NOTPRECOMPUTABLE_FLOW);
}
}