diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/module-utils.h | 34 | ||||
-rw-r--r-- | src/passes/Metrics.cpp | 45 |
2 files changed, 77 insertions, 2 deletions
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index 0c828f83a..5bcf2ea99 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -18,6 +18,7 @@ #define wasm_ir_module_h #include "wasm.h" +#include "ir/manipulation.h" namespace wasm { @@ -51,6 +52,39 @@ struct BinaryIndexes { } }; +inline void copyModule(Module& in, Module& out) { + // we use names throughout, not raw points, so simple copying is fine + // for everything *but* expressions + for (auto& curr : in.functionTypes) { + out.addFunctionType(new FunctionType(*curr)); + } + for (auto& curr : in.imports) { + out.addImport(new Import(*curr)); + } + for (auto& curr : in.exports) { + out.addExport(new Export(*curr)); + } + for (auto& curr : in.functions) { + auto* func = new Function(*curr); + func->body = ExpressionManipulator::copy(func->body, out); + out.addFunction(func); + } + for (auto& curr : in.globals) { + out.addGlobal(new Global(*curr)); + } + out.table = in.table; + for (auto& segment : out.table.segments) { + segment.offset = ExpressionManipulator::copy(segment.offset, out); + } + out.memory = in.memory; + for (auto& segment : out.memory.segments) { + segment.offset = ExpressionManipulator::copy(segment.offset, out); + } + out.start = in.start; + out.userSections = in.userSections; + out.debugInfoFileNames = in.debugInfoFileNames; +} + } // namespace ModuleUtils } // namespace wasm diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp index 822596cb3..5b5e1c8ab 100644 --- a/src/passes/Metrics.cpp +++ b/src/passes/Metrics.cpp @@ -20,6 +20,7 @@ #include <support/colors.h> #include <wasm.h> #include <wasm-binary.h> +#include <ir/module-utils.h> namespace wasm { @@ -92,7 +93,43 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor< counts["[binary-bytes]"] = writer.tableOfContents.functionBodies[i].size; printCounts(std::string("func: ") + func->name.str); } - // can't comapre detailed info between passes yet + // print for each export how much code size is due to it, i.e., + // how much the module could shrink without it. + auto sizeAfterGlobalCleanup = [](Module* module) { + PassRunner runner(module, PassOptions::getWithDefaultOptimizationOptions()); + runner.setIsNested(true); + runner.addDefaultGlobalOptimizationPostPasses(); // remove stuff + runner.run(); + BufferWithRandomAccess buffer; + WasmBinaryWriter writer(module, buffer); + writer.write(); + return buffer.size(); + }; + size_t baseline; + { + Module test; + ModuleUtils::copyModule(*module, test); + baseline = sizeAfterGlobalCleanup(&test); + } + for (auto& exp : module->exports) { + // create a test module where we remove the export and then see how much can be removed thanks to that + Module test; + ModuleUtils::copyModule(*module, test); + test.removeExport(exp->name); + counts.clear(); + counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test); + printCounts(std::string("export: ") + exp->name.str + " (" + exp->value.str + ')'); + } + // check how much size depends on the start method + if (!module->start.isNull()) { + Module test; + ModuleUtils::copyModule(*module, test); + test.start = Name(); + counts.clear(); + counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test); + printCounts(std::string("start: ") + module->start.str); + } + // can't compare detailed info between passes yet lastMetricsPass = nullptr; } else { // add function info @@ -116,7 +153,10 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor< int total = 0; for (auto i : counts) { keys.push_back(i.first); - total += i.second; + // total is of all the normal stuff, not the special [things] + if (i.first[0] != '[') { + total += i.second; + } } keys.push_back("[total]"); counts["[total]"] = total; @@ -127,6 +167,7 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor< o << title << "\n"; for (auto* key : keys) { auto value = counts[key]; + if (value == 0) continue; o << " " << left << setw(15) << key << ": " << setw(8) << value; if (lastMetricsPass) { |