diff options
-rw-r--r-- | src/passes/Precompute.cpp | 36 | ||||
-rw-r--r-- | test/passes/precompute-propagate.txt | 23 | ||||
-rw-r--r-- | test/passes/precompute-propagate.wast | 28 | ||||
-rw-r--r-- | test/wasm-only.fromasm | 19 | ||||
-rw-r--r-- | test/wasm-only.fromasm.clamp | 19 |
5 files changed, 84 insertions, 41 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index ed3d51701..db7d8b772 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -38,8 +38,15 @@ class StandaloneExpressionRunner : public ExpressionRunner<StandaloneExpressionR // map gets to constant values, if they are known to be constant GetValues& getValues; + // Whether we are trying to precompute down to an expression (which we can do on + // say 5 + 6) or to a value (which we can't do on a tee_local that flows a 7 + // through it). When we want to replace the expression, we can only do so + // when it has no side effects. When we don't care about replacing the expression, + // we just want to know if it will contain a known constant. + bool replaceExpression; + public: - StandaloneExpressionRunner(GetValues& getValues) : getValues(getValues) {} + StandaloneExpressionRunner(GetValues& getValues, bool replaceExpression) : getValues(getValues), replaceExpression(replaceExpression) {} struct NonstandaloneException {}; // TODO: use a flow with a special name, as this is likely very slow @@ -69,6 +76,14 @@ public: return Flow(NONSTANDALONE_FLOW); } Flow visitSetLocal(SetLocal *curr) { + // If we don't need to replace the whole expression, see if there + // is a value flowing through a tee. + if (!replaceExpression) { + if (isConcreteType(curr->type)) { + assert(curr->isTee()); + return visit(curr->value); + } + } return Flow(NONSTANDALONE_FLOW); } Flow visitGetGlobal(GetGlobal *curr) { @@ -130,7 +145,7 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi // 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 = precomputeFlow(curr); + Flow flow = precomputeExpression(curr); if (flow.breaking()) { if (flow.breakTo == NONSTANDALONE_FLOW) return; if (flow.breakTo == RETURN_FLOW) { @@ -194,16 +209,27 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi } private: - Flow precomputeFlow(Expression* curr) { + // Precompute an expression, returning a flow, which may be a constant + // (that we can replace the expression with if replaceExpression is set). + Flow precomputeExpression(Expression* curr, bool replaceExpression = true) { try { - return StandaloneExpressionRunner(getValues).visit(curr); + return StandaloneExpressionRunner(getValues, replaceExpression).visit(curr); } catch (StandaloneExpressionRunner::NonstandaloneException& e) { return Flow(NONSTANDALONE_FLOW); } } + // Precomputes the value of an expression, as opposed to the expression + // itself. This differs from precomputeExpression in that we care about + // the value the expression will have, which we cannot necessary replace + // the expression with. For example, + // (tee_local (i32.const 1)) + // will have value 1 which we can optimize here, but in precomputeExpression + // we could not do anything. Literal precomputeValue(Expression* curr) { - Flow flow = precomputeFlow(curr); + // Note that we set replaceExpression to false, as we just care about + // the value here. + Flow flow = precomputeExpression(curr, false /* replaceExpression */); if (flow.breaking()) { return Literal(); } diff --git a/test/passes/precompute-propagate.txt b/test/passes/precompute-propagate.txt index 262b4880c..15abe1f2e 100644 --- a/test/passes/precompute-propagate.txt +++ b/test/passes/precompute-propagate.txt @@ -1,6 +1,7 @@ (module (type $0 (func (param i32))) (type $1 (func (param i32) (result i32))) + (type $2 (func (param i32 i32) (result i32))) (func $basic (; 0 ;) (type $0) (param $p i32) (local $x i32) (set_local $x @@ -210,4 +211,26 @@ (br $loop) ) ) + (func $through-tee (; 13 ;) (type $2) (param $x i32) (param $y i32) (result i32) + (set_local $x + (tee_local $y + (i32.const 7) + ) + ) + (return + (i32.const 14) + ) + ) + (func $through-tee-more (; 14 ;) (type $2) (param $x i32) (param $y i32) (result i32) + (set_local $x + (i32.eqz + (tee_local $y + (i32.const 7) + ) + ) + ) + (return + (i32.const 7) + ) + ) ) diff --git a/test/passes/precompute-propagate.wast b/test/passes/precompute-propagate.wast index af1a21ba2..4cf440829 100644 --- a/test/passes/precompute-propagate.wast +++ b/test/passes/precompute-propagate.wast @@ -109,5 +109,33 @@ (br $loop) ) ) + (func $through-tee (param $x i32) (param $y i32) (result i32) + (set_local $x + (tee_local $y + (i32.const 7) + ) + ) + (return + (i32.add + (get_local $x) + (get_local $y) + ) + ) + ) + (func $through-tee-more (param $x i32) (param $y i32) (result i32) + (set_local $x + (i32.eqz + (tee_local $y + (i32.const 7) + ) + ) + ) + (return + (i32.add + (get_local $x) + (get_local $y) + ) + ) + ) ) diff --git a/test/wasm-only.fromasm b/test/wasm-only.fromasm index 596ab5eb6..f2c80a778 100644 --- a/test/wasm-only.fromasm +++ b/test/wasm-only.fromasm @@ -368,24 +368,7 @@ (local $2 f64) (set_local $0 (call $i64s-div - (block (result i64) - (set_local $0 - (i64.mul - (i64.sub - (i64.add - (i64.const 128849018897) - (i64.const 100) - ) - (i64.const 128849018897) - ) - (i64.const 128849018897) - ) - ) - (i64.div_u - (get_local $0) - (i64.const 128849018897) - ) - ) + (i64.const 100) (i64.const 128849018897) ) ) diff --git a/test/wasm-only.fromasm.clamp b/test/wasm-only.fromasm.clamp index 596ab5eb6..f2c80a778 100644 --- a/test/wasm-only.fromasm.clamp +++ b/test/wasm-only.fromasm.clamp @@ -368,24 +368,7 @@ (local $2 f64) (set_local $0 (call $i64s-div - (block (result i64) - (set_local $0 - (i64.mul - (i64.sub - (i64.add - (i64.const 128849018897) - (i64.const 100) - ) - (i64.const 128849018897) - ) - (i64.const 128849018897) - ) - ) - (i64.div_u - (get_local $0) - (i64.const 128849018897) - ) - ) + (i64.const 100) (i64.const 128849018897) ) ) |