summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Metrics.cpp42
-rw-r--r--src/tools/wasm-opt.cpp37
-rw-r--r--test/passes/converge_O3_metrics.bin.txt761
-rw-r--r--test/passes/converge_O3_metrics.wasmbin0 -> 1492 bytes
4 files changed, 812 insertions, 28 deletions
diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp
index 5b5e1c8ab..8cbf96db5 100644
--- a/src/passes/Metrics.cpp
+++ b/src/passes/Metrics.cpp
@@ -22,19 +22,21 @@
#include <wasm-binary.h>
#include <ir/module-utils.h>
+using namespace std;
+
namespace wasm {
-using namespace std;
+typedef map<const char *, int> Counts;
+
+static Counts lastCounts;
// Prints metrics between optimization passes.
struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<Metrics>>> {
bool byFunction;
- Metrics(bool byFunction) : byFunction(byFunction) {}
-
- static Metrics *lastMetricsPass;
+ Counts counts;
- map<const char *, int> counts;
+ Metrics(bool byFunction) : byFunction(byFunction) {}
void visitExpression(Expression* curr) {
auto name = getExpressionName(curr);
@@ -130,7 +132,7 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
printCounts(std::string("start: ") + module->start.str);
}
// can't compare detailed info between passes yet
- lastMetricsPass = nullptr;
+ lastCounts.clear();
} else {
// add function info
size_t vars = 0;
@@ -142,7 +144,7 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
// print
printCounts("total");
// compare to next time
- lastMetricsPass = this;
+ lastCounts = counts;
}
}
@@ -170,20 +172,18 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
if (value == 0) continue;
o << " " << left << setw(15) << key << ": " << setw(8)
<< value;
- if (lastMetricsPass) {
- if (lastMetricsPass->counts.count(key)) {
- int before = lastMetricsPass->counts[key];
- int after = value;
- if (after - before) {
- if (after > before) {
- Colors::red(o);
- } else {
- Colors::green(o);
- }
- o << right << setw(8);
- o << showpos << after - before << noshowpos;
- Colors::normal(o);
+ if (lastCounts.count(key)) {
+ int before = lastCounts[key];
+ int after = value;
+ if (after - before) {
+ if (after > before) {
+ Colors::red(o);
+ } else {
+ Colors::green(o);
}
+ o << right << setw(8);
+ o << showpos << after - before << noshowpos;
+ Colors::normal(o);
}
}
o << "\n";
@@ -199,6 +199,4 @@ Pass *createFunctionMetricsPass() {
return new Metrics(true);
}
-Metrics *Metrics::lastMetricsPass;
-
} // namespace wasm
diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp
index a82dc4a2f..7d7d44b2b 100644
--- a/src/tools/wasm-opt.cpp
+++ b/src/tools/wasm-opt.cpp
@@ -64,6 +64,7 @@ int main(int argc, const char* argv[]) {
Name entry;
bool emitBinary = true;
bool debugInfo = false;
+ bool converge = false;
bool fuzzExec = false;
bool fuzzBinary = false;
std::string extraFuzzCommand;
@@ -86,6 +87,9 @@ int main(int argc, const char* argv[]) {
.add("--debuginfo", "-g", "Emit names section and debug info",
Options::Arguments::Zero,
[&](Options *o, const std::string& arguments) { debugInfo = true; })
+ .add("--converge", "-c", "Run passes to convergence, continuing while binary size decreases",
+ Options::Arguments::Zero,
+ [&](Options *o, const std::string& arguments) { converge = true; })
.add("--fuzz-exec", "-fe", "Execute functions before and after optimization, helping fuzzing find bugs",
Options::Arguments::Zero,
[&](Options *o, const std::string& arguments) { fuzzExec = true; })
@@ -211,13 +215,34 @@ int main(int argc, const char* argv[]) {
if (options.runningPasses()) {
if (options.debug) std::cerr << "running passes...\n";
- options.runPasses(*curr);
- if (options.passOptions.validate) {
- bool valid = WasmValidator().validate(*curr, features);
- if (!valid) {
- WasmPrinter::printModule(&*curr);
+ auto runPasses = [&]() {
+ options.runPasses(*curr);
+ if (options.passOptions.validate) {
+ bool valid = WasmValidator().validate(*curr, features);
+ if (!valid) {
+ WasmPrinter::printModule(&*curr);
+ }
+ assert(valid);
+ }
+ };
+ runPasses();
+ if (converge) {
+ // Keep on running passes to convergence, defined as binary
+ // size no longer decreasing.
+ auto getSize = [&]() {
+ BufferWithRandomAccess buffer;
+ WasmBinaryWriter writer(curr, buffer);
+ writer.write();
+ return buffer.size();
+ };
+ auto lastSize = getSize();
+ while (1) {
+ if (options.debug) std::cerr << "running iteration for convergence (" << lastSize << ")...\n";
+ runPasses();
+ auto currSize = getSize();
+ if (currSize >= lastSize) break;
+ lastSize = currSize;
}
- assert(valid);
}
}
diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt
new file mode 100644
index 000000000..ab88c57d0
--- /dev/null
+++ b/test/passes/converge_O3_metrics.bin.txt
@@ -0,0 +1,761 @@
+total
+ [funcs] : 9
+ [memory-data] : 28
+ [table-data] : 429
+ [total] : 145
+ [vars] : 5
+ binary : 14
+ block : 9
+ break : 3
+ call : 3
+ call_import : 1
+ call_indirect : 4
+ const : 50
+ drop : 3
+ get_global : 1
+ get_local : 20
+ if : 3
+ load : 16
+ loop : 1
+ set_global : 1
+ set_local : 11
+ store : 5
+(module
+ (type $0 (func (param i32 i32) (result i32)))
+ (type $1 (func (param i32 i32 i32) (result i32)))
+ (type $2 (func (param i32) (result i32)))
+ (type $3 (func (param i32)))
+ (type $6 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32)))
+ (type $7 (func (result i32)))
+ (import "env" "memory" (memory $0 256 256))
+ (import "env" "table" (table 478 478 anyfunc))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
+ (global $global$0 (mut i32) (i32.const 1))
+ (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
+ (data (i32.const 2948) "\03")
+ (data (i32.const 6828) "\04")
+ (data (i32.const 7028) "\0d\00\00\00\06")
+ (data (i32.const 10888) "hello, world!")
+ (data (i32.const 18100) "\b8\1a")
+ (data (i32.const 18128) ",I")
+ (data (i32.const 18732) "D\1b")
+ (data (i32.const 18764) "`\0b")
+ (export "_main" (func $_main))
+ (export "_malloc" (func $_malloc))
+ (func $b0 (; 1 ;) (type $6) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $_malloc (; 2 ;) (type $2) (param $0 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $___stdio_write (; 3 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (i32.store
+ (i32.const 8)
+ (get_local $1)
+ )
+ (i32.store
+ (i32.const 12)
+ (get_local $2)
+ )
+ (i32.store
+ (tee_local $1
+ (get_global $global$0)
+ )
+ (i32.const 1)
+ )
+ (i32.store offset=8
+ (get_local $1)
+ (i32.const 2)
+ )
+ (drop
+ (if (result i32)
+ (call $import$0
+ (i32.const 146)
+ (get_local $1)
+ )
+ (i32.const -1)
+ (i32.const 0)
+ )
+ )
+ (i32.const 1)
+ )
+ (func $_main (; 4 ;) (type $7) (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (call $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j
+ (block (result i32)
+ (set_local $1
+ (tee_local $0
+ (i32.const 10888)
+ )
+ )
+ (loop $label$3
+ (br_if $label$3
+ (i32.load8_s
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (i32.sub
+ (get_local $0)
+ (i32.const 10888)
+ )
+ )
+ )
+ (call $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc
+ (i32.const 10)
+ )
+ (i32.const 0)
+ )
+ (func $___stdout_write (; 5 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (set_global $global$0
+ (i32.const 32)
+ )
+ (call $___stdio_write
+ (i32.const 1)
+ (get_local $1)
+ (get_local $2)
+ )
+ )
+ (func $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j (; 6 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (set_local $1
+ (i32.load offset=24
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18100)
+ )
+ )
+ )
+ (block $label$2
+ (if
+ (tee_local $0
+ (i32.sub
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 10888)
+ )
+ )
+ (i32.const 10888)
+ )
+ )
+ (br_if $label$2
+ (call_indirect (type $1)
+ (get_local $1)
+ (i32.const 10888)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=48
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc (; 7 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (block $label$1
+ (br_if $label$1
+ (if (result i32)
+ (i32.load
+ (i32.add
+ (tee_local $2
+ (tee_local $1
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18124)
+ )
+ )
+ )
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.const 0)
+ (call_indirect (type $0)
+ (get_local $2)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=52
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 422)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; 8 ;) (type $0) (param $0 i32) (param $1 i32) (result i32)
+ (i32.store8
+ (i32.const 0)
+ (get_local $1)
+ )
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 1)
+ (i32.add
+ (i32.load offset=36
+ (tee_local $0
+ (i32.load
+ (i32.add
+ (get_local $0)
+ (i32.const 32)
+ )
+ )
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; 9 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (get_local $1)
+ (get_local $2)
+ (i32.add
+ (i32.load offset=36
+ (tee_local $0
+ (i32.load offset=32
+ (get_local $0)
+ )
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+)
+total
+ [funcs] : 9
+ [memory-data] : 28
+ [table-data] : 429
+ [total] : 136 -9
+ [vars] : 4 -1
+ binary : 12 -2
+ block : 9
+ break : 3
+ call : 3
+ call_import : 1
+ call_indirect : 4
+ const : 48 -2
+ drop : 3
+ get_global : 1
+ get_local : 20
+ if : 3
+ load : 16
+ loop : 1
+ set_global : 1
+ set_local : 6 -5
+ store : 5
+(module
+ (type $0 (func (param i32 i32) (result i32)))
+ (type $1 (func (param i32 i32 i32) (result i32)))
+ (type $2 (func (param i32) (result i32)))
+ (type $3 (func (param i32)))
+ (type $6 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32)))
+ (type $7 (func (result i32)))
+ (import "env" "memory" (memory $0 256 256))
+ (import "env" "table" (table 478 478 anyfunc))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
+ (global $global$0 (mut i32) (i32.const 1))
+ (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
+ (data (i32.const 2948) "\03")
+ (data (i32.const 6828) "\04")
+ (data (i32.const 7028) "\0d\00\00\00\06")
+ (data (i32.const 10888) "hello, world!")
+ (data (i32.const 18100) "\b8\1a")
+ (data (i32.const 18128) ",I")
+ (data (i32.const 18732) "D\1b")
+ (data (i32.const 18764) "`\0b")
+ (export "_main" (func $_main))
+ (export "_malloc" (func $_malloc))
+ (func $b0 (; 1 ;) (type $6) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $_malloc (; 2 ;) (type $2) (param $0 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $___stdio_write (; 3 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (i32.store
+ (i32.const 8)
+ (get_local $1)
+ )
+ (i32.store
+ (i32.const 12)
+ (get_local $2)
+ )
+ (i32.store
+ (tee_local $1
+ (get_global $global$0)
+ )
+ (i32.const 1)
+ )
+ (i32.store offset=8
+ (get_local $1)
+ (i32.const 2)
+ )
+ (drop
+ (if (result i32)
+ (call $import$0
+ (i32.const 146)
+ (get_local $1)
+ )
+ (i32.const -1)
+ (i32.const 0)
+ )
+ )
+ (i32.const 1)
+ )
+ (func $_main (; 4 ;) (type $7) (result i32)
+ (local $0 i32)
+ (call $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j
+ (block (result i32)
+ (set_local $0
+ (i32.const 10888)
+ )
+ (loop $label$3
+ (br_if $label$3
+ (i32.load8_s
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (i32.sub
+ (get_local $0)
+ (i32.const 10888)
+ )
+ )
+ )
+ (call $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc
+ (i32.const 10)
+ )
+ (i32.const 0)
+ )
+ (func $___stdout_write (; 5 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (set_global $global$0
+ (i32.const 32)
+ )
+ (call $___stdio_write
+ (i32.const 1)
+ (get_local $1)
+ (get_local $2)
+ )
+ )
+ (func $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j (; 6 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (set_local $1
+ (i32.load offset=24
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18100)
+ )
+ )
+ )
+ (block $label$2
+ (if
+ (get_local $0)
+ (br_if $label$2
+ (call_indirect (type $1)
+ (get_local $1)
+ (i32.const 10888)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=48
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc (; 7 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (block $label$1
+ (br_if $label$1
+ (if (result i32)
+ (i32.load
+ (i32.add
+ (tee_local $2
+ (tee_local $1
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18124)
+ )
+ )
+ )
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.const 0)
+ (call_indirect (type $0)
+ (get_local $2)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=52
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 422)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; 8 ;) (type $0) (param $0 i32) (param $1 i32) (result i32)
+ (i32.store8
+ (i32.const 0)
+ (get_local $1)
+ )
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 1)
+ (i32.add
+ (i32.load offset=36
+ (i32.load
+ (i32.add
+ (get_local $0)
+ (i32.const 32)
+ )
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; 9 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (get_local $1)
+ (get_local $2)
+ (i32.add
+ (i32.load offset=36
+ (i32.load offset=32
+ (get_local $0)
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+)
+total
+ [funcs] : 9
+ [memory-data] : 28
+ [table-data] : 429
+ [total] : 136
+ [vars] : 4
+ binary : 12
+ block : 9
+ break : 3
+ call : 3
+ call_import : 1
+ call_indirect : 4
+ const : 48
+ drop : 3
+ get_global : 1
+ get_local : 20
+ if : 3
+ load : 16
+ loop : 1
+ set_global : 1
+ set_local : 6
+ store : 5
+(module
+ (type $0 (func (param i32 i32) (result i32)))
+ (type $1 (func (param i32 i32 i32) (result i32)))
+ (type $2 (func (param i32) (result i32)))
+ (type $3 (func (param i32)))
+ (type $6 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32)))
+ (type $7 (func (result i32)))
+ (import "env" "memory" (memory $0 256 256))
+ (import "env" "table" (table 478 478 anyfunc))
+ (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32)))
+ (global $global$0 (mut i32) (i32.const 1))
+ (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi)
+ (data (i32.const 2948) "\03")
+ (data (i32.const 6828) "\04")
+ (data (i32.const 7028) "\0d\00\00\00\06")
+ (data (i32.const 10888) "hello, world!")
+ (data (i32.const 18100) "\b8\1a")
+ (data (i32.const 18128) ",I")
+ (data (i32.const 18732) "D\1b")
+ (data (i32.const 18764) "`\0b")
+ (export "_main" (func $_main))
+ (export "_malloc" (func $_malloc))
+ (func $b0 (; 1 ;) (type $6) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $_malloc (; 2 ;) (type $2) (param $0 i32) (result i32)
+ (i32.const 0)
+ )
+ (func $___stdio_write (; 3 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (i32.store
+ (i32.const 8)
+ (get_local $1)
+ )
+ (i32.store
+ (i32.const 12)
+ (get_local $2)
+ )
+ (i32.store
+ (tee_local $1
+ (get_global $global$0)
+ )
+ (i32.const 1)
+ )
+ (i32.store offset=8
+ (get_local $1)
+ (i32.const 2)
+ )
+ (drop
+ (if (result i32)
+ (call $import$0
+ (i32.const 146)
+ (get_local $1)
+ )
+ (i32.const -1)
+ (i32.const 0)
+ )
+ )
+ (i32.const 1)
+ )
+ (func $_main (; 4 ;) (type $7) (result i32)
+ (local $0 i32)
+ (call $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j
+ (block (result i32)
+ (set_local $0
+ (i32.const 10888)
+ )
+ (loop $label$3
+ (br_if $label$3
+ (i32.load8_s
+ (tee_local $0
+ (i32.add
+ (get_local $0)
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ )
+ (i32.sub
+ (get_local $0)
+ (i32.const 10888)
+ )
+ )
+ )
+ (call $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc
+ (i32.const 10)
+ )
+ (i32.const 0)
+ )
+ (func $___stdout_write (; 5 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (set_global $global$0
+ (i32.const 32)
+ )
+ (call $___stdio_write
+ (i32.const 1)
+ (get_local $1)
+ (get_local $2)
+ )
+ )
+ (func $__ZNSt3__224__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j (; 6 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (set_local $1
+ (i32.load offset=24
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18100)
+ )
+ )
+ )
+ (block $label$2
+ (if
+ (get_local $0)
+ (br_if $label$2
+ (call_indirect (type $1)
+ (get_local $1)
+ (i32.const 10888)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=48
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc (; 7 ;) (type $3) (param $0 i32)
+ (local $1 i32)
+ (local $2 i32)
+ (block $label$1
+ (br_if $label$1
+ (if (result i32)
+ (i32.load
+ (i32.add
+ (tee_local $2
+ (tee_local $1
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.add
+ (i32.load
+ (i32.const 18100)
+ )
+ (i32.const -12)
+ )
+ )
+ (i32.const 18124)
+ )
+ )
+ )
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.const 0)
+ (call_indirect (type $0)
+ (get_local $2)
+ (get_local $0)
+ (i32.add
+ (i32.load offset=52
+ (i32.load
+ (get_local $1)
+ )
+ )
+ (i32.const 422)
+ )
+ )
+ )
+ )
+ )
+ )
+ (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; 8 ;) (type $0) (param $0 i32) (param $1 i32) (result i32)
+ (i32.store8
+ (i32.const 0)
+ (get_local $1)
+ )
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (i32.const 0)
+ (i32.const 1)
+ (i32.add
+ (i32.load offset=36
+ (i32.load
+ (i32.add
+ (get_local $0)
+ (i32.const 32)
+ )
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; 9 ;) (type $1) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+ (drop
+ (call_indirect (type $1)
+ (i32.const 0)
+ (get_local $1)
+ (get_local $2)
+ (i32.add
+ (i32.load offset=36
+ (i32.load offset=32
+ (get_local $0)
+ )
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+)
diff --git a/test/passes/converge_O3_metrics.wasm b/test/passes/converge_O3_metrics.wasm
new file mode 100644
index 000000000..a1cc9a967
--- /dev/null
+++ b/test/passes/converge_O3_metrics.wasm
Binary files differ