diff options
-rw-r--r-- | src/passes/Precompute.cpp | 27 | ||||
-rw-r--r-- | test/passes/precompute-propagate.txt | 7 | ||||
-rw-r--r-- | test/passes/precompute-propagate.wast | 16 |
3 files changed, 42 insertions, 8 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index db7d8b772..32f54721d 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -130,15 +130,24 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi GetValues getValues; + bool worked; + 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); - } - // do the main and final walk over everything - super::doWalkFunction(func); + // if propagating, we may need multiple rounds: each propagation can + // lead to the main walk removing code, which might open up more + // propagation opportunities + do { + getValues.clear(); + // 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); + } + // do the main walk over everything + worked = false; + super::doWalkFunction(func); + } while (propagate && worked); } void visitExpression(Expression* curr) { @@ -198,6 +207,7 @@ struct Precompute : public WalkerPass<PostWalker<Precompute, UnifiedExpressionVi // this was precomputed if (isConcreteType(flow.value.type)) { replaceCurrent(Builder(*getModule()).makeConst(flow.value)); + worked = true; } else { ExpressionManipulator::nop(curr); } @@ -236,6 +246,7 @@ private: return flow.value; } + // Propagates values around. Returns whether we propagated. void optimizeLocals(Function* func) { // 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 diff --git a/test/passes/precompute-propagate.txt b/test/passes/precompute-propagate.txt index 15abe1f2e..919d8f3e7 100644 --- a/test/passes/precompute-propagate.txt +++ b/test/passes/precompute-propagate.txt @@ -2,6 +2,7 @@ (type $0 (func (param i32))) (type $1 (func (param i32) (result i32))) (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (param i32 i32 i32) (result i32))) (func $basic (; 0 ;) (type $0) (param $p i32) (local $x i32) (set_local $x @@ -233,4 +234,10 @@ (i32.const 7) ) ) + (func $multipass (; 15 ;) (type $3) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (nop) + (nop) + (get_local $2) + ) ) diff --git a/test/passes/precompute-propagate.wast b/test/passes/precompute-propagate.wast index 4cf440829..5cdc720ba 100644 --- a/test/passes/precompute-propagate.wast +++ b/test/passes/precompute-propagate.wast @@ -137,5 +137,21 @@ ) ) ) + (func $multipass (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (get_local $3) + (set_local $3 ;; this set is completely removed, allowing later opts + (i32.const 24) + ) + ) + (if + (get_local $3) + (set_local $2 + (i32.const 0) + ) + ) + (get_local $2) + ) ) |