outlining eval pass
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index bd1dd85..25750bb 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt
@@ -45,6 +45,7 @@ GlobalTypeOptimization.cpp GUFA.cpp hash-stringify-walker.cpp + outlining.cpp Heap2Local.cpp I64ToI32Lowering.cpp Inlining.cpp
diff --git a/src/passes/hash-stringify-walker.cpp b/src/passes/hash-stringify-walker.cpp index abcd071..fc60727 100644 --- a/src/passes/hash-stringify-walker.cpp +++ b/src/passes/hash-stringify-walker.cpp
@@ -70,6 +70,25 @@ } } +std::vector<SuffixTree::RepeatedSubstring> +StringifyProcessor::repeatSubstrings(const std::vector<uint32_t>& hashString) { + SuffixTree st(hashString); + std::vector<SuffixTree::RepeatedSubstring> substrings = + std::vector(st.begin(), st.end()); + std::sort( + substrings.begin(), + substrings.end(), + [](SuffixTree::RepeatedSubstring a, SuffixTree::RepeatedSubstring b) { + size_t aWeight = a.Length * a.StartIndices.size(); + size_t bWeight = b.Length * b.StartIndices.size(); + if (aWeight == bWeight) { + return a.StartIndices[0] < b.StartIndices[0]; + } + return aWeight > bWeight; + }); + return substrings; +} + // Deduplicate substrings by iterating through the list of substrings, keeping // only those whose list of end indices is disjoint from the set of end indices // for all substrings kept so far. Substrings that are contained within other @@ -112,7 +131,7 @@ std::vector<SuffixTree::RepeatedSubstring> StringifyProcessor::filter( const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs, + const std::vector<Expression*>& exprs, std::function<bool(const Expression*)> condition) { struct FilterStringifyWalker : public StringifyWalker<FilterStringifyWalker> { @@ -168,7 +187,7 @@ std::vector<SuffixTree::RepeatedSubstring> StringifyProcessor::filterLocalSets( const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs) { + const std::vector<Expression*>& exprs) { return StringifyProcessor::filter( substrings, exprs, [](const Expression* curr) { return curr->is<LocalSet>(); @@ -177,10 +196,11 @@ std::vector<SuffixTree::RepeatedSubstring> StringifyProcessor::filterBranches( const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs) { + const std::vector<Expression*>& exprs) { return StringifyProcessor::filter( substrings, exprs, [](const Expression* curr) { return Properties::isBranch(curr) || curr->is<Return>(); }); } + } // namespace wasm
diff --git a/src/passes/outlining.cpp b/src/passes/outlining.cpp new file mode 100644 index 0000000..30433e4 --- /dev/null +++ b/src/passes/outlining.cpp
@@ -0,0 +1,42 @@ +#include "ir/utils.h" +#include "pass.h" +#include "passes/stringify-walker.h" +#include "support/suffix_tree.h" +#include "wasm.h" + +namespace wasm { + +struct OutliningEval : public Pass { + void run(Module* module) { + HashStringifyWalker stringify = HashStringifyWalker(); + stringify.walkModule(module); + auto substrings = + StringifyProcessor::repeatSubstrings(stringify.hashString); + auto result = StringifyProcessor::dedupe(substrings); + result = StringifyProcessor::filterBranches(result, stringify.exprs); + result = StringifyProcessor::filterLocalSets(result, stringify.exprs); + printStats(substrings, result, &stringify); + } + + void printStats(std::vector<SuffixTree::RepeatedSubstring> substrings, + std::vector<SuffixTree::RepeatedSubstring> result, + HashStringifyWalker* stringify) { + std::cout << substrings.size() << " substrings found, "; + std::cout << "reduced to " << result.size() << std::endl; + for (auto rs : result) { + size_t startIndex = rs.StartIndices[0]; + std::cout << rs.StartIndices.size() << "x, ~" + << rs.StartIndices.size() * rs.Length * Measurer::BytesPerExpr + << " size:"; + for (size_t i = startIndex; i < startIndex + rs.Length; i++) { + std::cout << stringify->hashString[i] << " (" + << ShallowExpression{stringify->exprs[i]} << "), "; + } + std::cout << std::endl; + } + } +}; + +Pass* createOutliningEvalPass() { return new OutliningEval(); } + +} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 35085c2..804b0fc 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp
@@ -311,6 +311,9 @@ createOptimizeInstructionsPass); registerPass( "optimize-stack-ir", "optimize Stack IR", createOptimizeStackIRPass); + registerPass("outlining-eval", + "evaluate outlining feasibility", + createOutliningEvalPass); registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h index 2bace5b..c94d398 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h
@@ -99,6 +99,7 @@ Pass* createOptimizeCastsPass(); Pass* createOptimizeForJSPass(); Pass* createOptimizeStackIRPass(); +Pass* createOutliningEvalPass(); Pass* createPickLoadSignsPass(); Pass* createModAsyncifyAlwaysOnlyUnwindPass(); Pass* createModAsyncifyNeverUnwindPass();
diff --git a/src/passes/stringify-walker.h b/src/passes/stringify-walker.h index 6095eb7..d2e5134 100644 --- a/src/passes/stringify-walker.h +++ b/src/passes/stringify-walker.h
@@ -234,20 +234,22 @@ // Functions that filter vectors of SuffixTree::RepeatedSubstring struct StringifyProcessor { static std::vector<SuffixTree::RepeatedSubstring> + repeatSubstrings(const std::vector<uint32_t>& hashString); + static std::vector<SuffixTree::RepeatedSubstring> dedupe(const std::vector<SuffixTree::RepeatedSubstring>& substrings); // Filter is the general purpose function backing subsequent filter functions. // It can be used directly, but generally prefer a wrapper function // to encapsulate your condition and make it available for tests static std::vector<SuffixTree::RepeatedSubstring> filter(const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs, + const std::vector<Expression*>& exprs, std::function<bool(const Expression*)> condition); static std::vector<SuffixTree::RepeatedSubstring> filterLocalSets(const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs); + const std::vector<Expression*>& exprs); static std::vector<SuffixTree::RepeatedSubstring> filterBranches(const std::vector<SuffixTree::RepeatedSubstring>& substrings, - const std::vector<Expression*> exprs); + const std::vector<Expression*>& exprs); }; } // namespace wasm
diff --git a/test/gtest/stringify.cpp b/test/gtest/stringify.cpp index 8e854ee..59b7db6 100644 --- a/test/gtest/stringify.cpp +++ b/test/gtest/stringify.cpp
@@ -250,29 +250,11 @@ })); } -std::vector<SuffixTree::RepeatedSubstring> -repeatSubstrings(std::vector<uint32_t> hashString) { - SuffixTree st(hashString); - std::vector<SuffixTree::RepeatedSubstring> substrings(st.begin(), st.end()); - std::sort( - substrings.begin(), - substrings.end(), - [](SuffixTree::RepeatedSubstring a, SuffixTree::RepeatedSubstring b) { - size_t aWeight = a.Length * a.StartIndices.size(); - size_t bWeight = b.Length * b.StartIndices.size(); - if (aWeight == bWeight) { - return a.StartIndices[0] < b.StartIndices[0]; - } - return aWeight > bWeight; - }); - return substrings; -} - TEST_F(StringifyTest, Substrings) { Module wasm; parseWast(wasm, dupModuleText); auto hashString = hashStringifyModule(&wasm); - auto substrings = repeatSubstrings(hashString); + auto substrings = StringifyProcessor::repeatSubstrings(hashString); EXPECT_EQ( substrings, @@ -294,7 +276,7 @@ parseWast(wasm, dupModuleText); auto hashString = hashStringifyModule(&wasm); std::vector<SuffixTree::RepeatedSubstring> substrings = - repeatSubstrings(hashString); + StringifyProcessor::repeatSubstrings(hashString); auto result = StringifyProcessor::dedupe(substrings); EXPECT_EQ( @@ -332,10 +314,9 @@ parseWast(wasm, localSetModuleText); HashStringifyWalker stringify = HashStringifyWalker(); stringify.walkModule(&wasm); - auto substrings = repeatSubstrings(stringify.hashString); - auto result = StringifyProcessor::dedupe(substrings); - - result = StringifyProcessor::filterLocalSets(substrings, stringify.exprs); + auto substrings = StringifyProcessor::repeatSubstrings(stringify.hashString); + auto result = + StringifyProcessor::filterLocalSets(substrings, stringify.exprs); EXPECT_EQ( result, @@ -375,8 +356,7 @@ parseWast(wasm, branchesModuleText); HashStringifyWalker stringify = HashStringifyWalker(); stringify.walkModule(&wasm); - - auto substrings = repeatSubstrings(stringify.hashString); + auto substrings = StringifyProcessor::repeatSubstrings(stringify.hashString); auto result = StringifyProcessor::filterBranches(substrings, stringify.exprs); EXPECT_EQ(