diff options
author | Daniel Wirtz <dcode@dcode.io> | 2018-07-18 19:16:29 +0200 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2018-07-18 10:16:29 -0700 |
commit | 25890f53cba4b9b05341ac146dde755a7fa4fddd (patch) | |
tree | 6fe6ca4b9401dc59df1d9b9d2aded6d70005b4df /src/passes/Precompute.cpp | |
parent | e601522b1e15e5a2a96578244faca1648021fb2d (diff) | |
download | binaryen-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.cpp | 54 |
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); } } |