Skip to content

Commit 7a4c47e

Browse files
dcodeIOkripken
authored andcommitted
Added the ability to run specific optimization passes to binaryen-c/.js (#1252)
1 parent da871de commit 7a4c47e

10 files changed

Lines changed: 1466 additions & 1337 deletions

File tree

bin/binaryen.js

Lines changed: 708 additions & 666 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/wasm.js

Lines changed: 694 additions & 649 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build-js.sh

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,24 @@ echo "building shared bitcode"
6464

6565
"$EMSCRIPTEN/em++" \
6666
$EMCC_ARGS \
67-
src/ast/ExpressionAnalyzer.cpp \
68-
src/ast/ExpressionManipulator.cpp \
69-
src/ast/LocalGraph.cpp \
67+
src/asmjs/asm_v_wasm.cpp \
68+
src/asmjs/shared-constants.cpp \
69+
src/cfg/Relooper.cpp \
70+
src/emscripten-optimizer/optimizer-shared.cpp \
71+
src/emscripten-optimizer/parser.cpp \
72+
src/emscripten-optimizer/simple_ast.cpp \
73+
src/ir/ExpressionAnalyzer.cpp \
74+
src/ir/ExpressionManipulator.cpp \
75+
src/ir/LocalGraph.cpp \
7076
src/passes/pass.cpp \
7177
src/passes/CoalesceLocals.cpp \
7278
src/passes/CodeFolding.cpp \
7379
src/passes/CodePushing.cpp \
80+
src/passes/ConstHoisting.cpp \
7481
src/passes/DeadCodeElimination.cpp \
7582
src/passes/DuplicateFunctionElimination.cpp \
7683
src/passes/ExtractFunction.cpp \
77-
src/passes/FlattenControlFlow.cpp \
84+
src/passes/Flatten.cpp \
7885
src/passes/I64ToI32Lowering.cpp \
7986
src/passes/Inlining.cpp \
8087
src/passes/InstrumentLocals.cpp \
@@ -90,8 +97,8 @@ echo "building shared bitcode"
9097
src/passes/PickLoadSigns.cpp \
9198
src/passes/PostEmscripten.cpp \
9299
src/passes/Precompute.cpp \
93-
src/passes/PrintCallGraph.cpp \
94100
src/passes/Print.cpp \
101+
src/passes/PrintCallGraph.cpp \
95102
src/passes/RelooperJumpThreading.cpp \
96103
src/passes/RemoveImports.cpp \
97104
src/passes/RemoveMemory.cpp \
@@ -101,29 +108,23 @@ echo "building shared bitcode"
101108
src/passes/ReorderFunctions.cpp \
102109
src/passes/ReorderLocals.cpp \
103110
src/passes/ReReloop.cpp \
104-
src/passes/ConstHoisting.cpp \
105111
src/passes/SafeHeap.cpp \
106-
src/passes/SSAify.cpp \
107112
src/passes/SimplifyLocals.cpp \
113+
src/passes/SSAify.cpp \
114+
src/passes/TrapMode.cpp \
108115
src/passes/Untee.cpp \
109116
src/passes/Vacuum.cpp \
110-
src/emscripten-optimizer/parser.cpp \
111-
src/emscripten-optimizer/simple_ast.cpp \
112-
src/emscripten-optimizer/optimizer-shared.cpp \
113-
src/wasm-emscripten.cpp \
117+
src/support/bits.cpp \
114118
src/support/colors.cpp \
115119
src/support/safe_integer.cpp \
116-
src/support/bits.cpp \
117120
src/support/threads.cpp \
118-
src/asmjs/asm_v_wasm.cpp \
119-
src/asmjs/shared-constants.cpp \
120-
src/wasm/wasm.cpp \
121-
src/wasm/wasm-type.cpp \
122-
src/wasm/wasm-s-parser.cpp \
121+
src/wasm/literal.cpp \
123122
src/wasm/wasm-binary.cpp \
123+
src/wasm/wasm-s-parser.cpp \
124+
src/wasm/wasm-type.cpp \
124125
src/wasm/wasm-validator.cpp \
125-
src/wasm/literal.cpp \
126-
src/cfg/Relooper.cpp \
126+
src/wasm/wasm.cpp \
127+
src/wasm-emscripten.cpp \
127128
-Isrc/ \
128129
-o shared.bc
129130

@@ -145,7 +146,7 @@ echo "building binaryen.js"
145146
src/binaryen-c.cpp \
146147
shared.bc \
147148
-Isrc/ \
148-
-s 'EXPORTED_FUNCTIONS=["_BinaryenNone", "_BinaryenInt32", "_BinaryenInt64", "_BinaryenFloat32", "_BinaryenFloat64", "_BinaryenUndefined", "_BinaryenModuleCreate", "_BinaryenModuleDispose", "_BinaryenAddFunctionType", "_BinaryenGetFunctionTypeBySignature", "_BinaryenLiteralInt32", "_BinaryenLiteralInt64", "_BinaryenLiteralFloat32", "_BinaryenLiteralFloat64", "_BinaryenLiteralFloat32Bits", "_BinaryenLiteralFloat64Bits", "_BinaryenClzInt32", "_BinaryenCtzInt32", "_BinaryenPopcntInt32", "_BinaryenNegFloat32", "_BinaryenAbsFloat32", "_BinaryenCeilFloat32", "_BinaryenFloorFloat32", "_BinaryenTruncFloat32", "_BinaryenNearestFloat32", "_BinaryenSqrtFloat32", "_BinaryenEqZInt32", "_BinaryenClzInt64", "_BinaryenCtzInt64", "_BinaryenPopcntInt64", "_BinaryenNegFloat64", "_BinaryenAbsFloat64", "_BinaryenCeilFloat64", "_BinaryenFloorFloat64", "_BinaryenTruncFloat64", "_BinaryenNearestFloat64", "_BinaryenSqrtFloat64", "_BinaryenEqZInt64", "_BinaryenExtendSInt32", "_BinaryenExtendUInt32", "_BinaryenWrapInt64", "_BinaryenTruncSFloat32ToInt32", "_BinaryenTruncSFloat32ToInt64", "_BinaryenTruncUFloat32ToInt32", "_BinaryenTruncUFloat32ToInt64", "_BinaryenTruncSFloat64ToInt32", "_BinaryenTruncSFloat64ToInt64", "_BinaryenTruncUFloat64ToInt32", "_BinaryenTruncUFloat64ToInt64", "_BinaryenReinterpretFloat32", "_BinaryenReinterpretFloat64", "_BinaryenConvertSInt32ToFloat32", "_BinaryenConvertSInt32ToFloat64", "_BinaryenConvertUInt32ToFloat32", "_BinaryenConvertUInt32ToFloat64", "_BinaryenConvertSInt64ToFloat32", "_BinaryenConvertSInt64ToFloat64", "_BinaryenConvertUInt64ToFloat32", "_BinaryenConvertUInt64ToFloat64", "_BinaryenPromoteFloat32", "_BinaryenDemoteFloat64", "_BinaryenReinterpretInt32", "_BinaryenReinterpretInt64", "_BinaryenAddInt32", "_BinaryenSubInt32", "_BinaryenMulInt32", "_BinaryenDivSInt32", "_BinaryenDivUInt32", "_BinaryenRemSInt32", "_BinaryenRemUInt32", "_BinaryenAndInt32", "_BinaryenOrInt32", "_BinaryenXorInt32", "_BinaryenShlInt32", "_BinaryenShrUInt32", "_BinaryenShrSInt32", "_BinaryenRotLInt32", "_BinaryenRotRInt32", "_BinaryenEqInt32", "_BinaryenNeInt32", "_BinaryenLtSInt32", "_BinaryenLtUInt32", "_BinaryenLeSInt32", "_BinaryenLeUInt32", "_BinaryenGtSInt32", "_BinaryenGtUInt32", "_BinaryenGeSInt32", "_BinaryenGeUInt32", "_BinaryenAddInt64", "_BinaryenSubInt64", "_BinaryenMulInt64", "_BinaryenDivSInt64", "_BinaryenDivUInt64", "_BinaryenRemSInt64", "_BinaryenRemUInt64", "_BinaryenAndInt64", "_BinaryenOrInt64", "_BinaryenXorInt64", "_BinaryenShlInt64", "_BinaryenShrUInt64", "_BinaryenShrSInt64", "_BinaryenRotLInt64", "_BinaryenRotRInt64", "_BinaryenEqInt64", "_BinaryenNeInt64", "_BinaryenLtSInt64", "_BinaryenLtUInt64", "_BinaryenLeSInt64", "_BinaryenLeUInt64", "_BinaryenGtSInt64", "_BinaryenGtUInt64", "_BinaryenGeSInt64", "_BinaryenGeUInt64", "_BinaryenAddFloat32", "_BinaryenSubFloat32", "_BinaryenMulFloat32", "_BinaryenDivFloat32", "_BinaryenCopySignFloat32", "_BinaryenMinFloat32", "_BinaryenMaxFloat32", "_BinaryenEqFloat32", "_BinaryenNeFloat32", "_BinaryenLtFloat32", "_BinaryenLeFloat32", "_BinaryenGtFloat32", "_BinaryenGeFloat32", "_BinaryenAddFloat64", "_BinaryenSubFloat64", "_BinaryenMulFloat64", "_BinaryenDivFloat64", "_BinaryenCopySignFloat64", "_BinaryenMinFloat64", "_BinaryenMaxFloat64", "_BinaryenEqFloat64", "_BinaryenNeFloat64", "_BinaryenLtFloat64", "_BinaryenLeFloat64", "_BinaryenGtFloat64", "_BinaryenGeFloat64", "_BinaryenPageSize", "_BinaryenCurrentMemory", "_BinaryenGrowMemory", "_BinaryenHasFeature", "_BinaryenBlock", "_BinaryenIf", "_BinaryenLoop", "_BinaryenBreak", "_BinaryenSwitch", "_BinaryenCall", "_BinaryenCallImport", "_BinaryenCallIndirect", "_BinaryenGetLocal", "_BinaryenSetLocal", "_BinaryenTeeLocal", "_BinaryenGetGlobal", "_BinaryenSetGlobal", "_BinaryenLoad", "_BinaryenStore", "_BinaryenConst", "_BinaryenUnary", "_BinaryenBinary", "_BinaryenSelect", "_BinaryenDrop", "_BinaryenReturn", "_BinaryenHost", "_BinaryenNop", "_BinaryenUnreachable", "_BinaryenExpressionPrint", "_BinaryenAddFunction", "_BinaryenAddGlobal", "_BinaryenAddImport", "_BinaryenRemoveImport", "_BinaryenAddExport", "_BinaryenRemoveExport", "_BinaryenSetFunctionTable", "_BinaryenSetMemory", "_BinaryenSetStart", "_BinaryenModuleParse", "_BinaryenModulePrint", "_BinaryenModulePrintAsmjs", "_BinaryenModuleValidate", "_BinaryenModuleOptimize", "_BinaryenModuleAutoDrop", "_BinaryenModuleWrite", "_BinaryenModuleRead", "_BinaryenModuleInterpret", "_RelooperCreate", "_RelooperAddBlock", "_RelooperAddBranch", "_RelooperAddBlockWithSwitch", "_RelooperAddBranchForSwitch", "_RelooperRenderAndDispose", "_BinaryenSetAPITracing"]' \
149+
-s 'EXPORTED_FUNCTIONS=["_BinaryenNone", "_BinaryenInt32", "_BinaryenInt64", "_BinaryenFloat32", "_BinaryenFloat64", "_BinaryenUndefined", "_BinaryenModuleCreate", "_BinaryenModuleDispose", "_BinaryenAddFunctionType", "_BinaryenGetFunctionTypeBySignature", "_BinaryenLiteralInt32", "_BinaryenLiteralInt64", "_BinaryenLiteralFloat32", "_BinaryenLiteralFloat64", "_BinaryenLiteralFloat32Bits", "_BinaryenLiteralFloat64Bits", "_BinaryenClzInt32", "_BinaryenCtzInt32", "_BinaryenPopcntInt32", "_BinaryenNegFloat32", "_BinaryenAbsFloat32", "_BinaryenCeilFloat32", "_BinaryenFloorFloat32", "_BinaryenTruncFloat32", "_BinaryenNearestFloat32", "_BinaryenSqrtFloat32", "_BinaryenEqZInt32", "_BinaryenClzInt64", "_BinaryenCtzInt64", "_BinaryenPopcntInt64", "_BinaryenNegFloat64", "_BinaryenAbsFloat64", "_BinaryenCeilFloat64", "_BinaryenFloorFloat64", "_BinaryenTruncFloat64", "_BinaryenNearestFloat64", "_BinaryenSqrtFloat64", "_BinaryenEqZInt64", "_BinaryenExtendSInt32", "_BinaryenExtendUInt32", "_BinaryenWrapInt64", "_BinaryenTruncSFloat32ToInt32", "_BinaryenTruncSFloat32ToInt64", "_BinaryenTruncUFloat32ToInt32", "_BinaryenTruncUFloat32ToInt64", "_BinaryenTruncSFloat64ToInt32", "_BinaryenTruncSFloat64ToInt64", "_BinaryenTruncUFloat64ToInt32", "_BinaryenTruncUFloat64ToInt64", "_BinaryenReinterpretFloat32", "_BinaryenReinterpretFloat64", "_BinaryenConvertSInt32ToFloat32", "_BinaryenConvertSInt32ToFloat64", "_BinaryenConvertUInt32ToFloat32", "_BinaryenConvertUInt32ToFloat64", "_BinaryenConvertSInt64ToFloat32", "_BinaryenConvertSInt64ToFloat64", "_BinaryenConvertUInt64ToFloat32", "_BinaryenConvertUInt64ToFloat64", "_BinaryenPromoteFloat32", "_BinaryenDemoteFloat64", "_BinaryenReinterpretInt32", "_BinaryenReinterpretInt64", "_BinaryenAddInt32", "_BinaryenSubInt32", "_BinaryenMulInt32", "_BinaryenDivSInt32", "_BinaryenDivUInt32", "_BinaryenRemSInt32", "_BinaryenRemUInt32", "_BinaryenAndInt32", "_BinaryenOrInt32", "_BinaryenXorInt32", "_BinaryenShlInt32", "_BinaryenShrUInt32", "_BinaryenShrSInt32", "_BinaryenRotLInt32", "_BinaryenRotRInt32", "_BinaryenEqInt32", "_BinaryenNeInt32", "_BinaryenLtSInt32", "_BinaryenLtUInt32", "_BinaryenLeSInt32", "_BinaryenLeUInt32", "_BinaryenGtSInt32", "_BinaryenGtUInt32", "_BinaryenGeSInt32", "_BinaryenGeUInt32", "_BinaryenAddInt64", "_BinaryenSubInt64", "_BinaryenMulInt64", "_BinaryenDivSInt64", "_BinaryenDivUInt64", "_BinaryenRemSInt64", "_BinaryenRemUInt64", "_BinaryenAndInt64", "_BinaryenOrInt64", "_BinaryenXorInt64", "_BinaryenShlInt64", "_BinaryenShrUInt64", "_BinaryenShrSInt64", "_BinaryenRotLInt64", "_BinaryenRotRInt64", "_BinaryenEqInt64", "_BinaryenNeInt64", "_BinaryenLtSInt64", "_BinaryenLtUInt64", "_BinaryenLeSInt64", "_BinaryenLeUInt64", "_BinaryenGtSInt64", "_BinaryenGtUInt64", "_BinaryenGeSInt64", "_BinaryenGeUInt64", "_BinaryenAddFloat32", "_BinaryenSubFloat32", "_BinaryenMulFloat32", "_BinaryenDivFloat32", "_BinaryenCopySignFloat32", "_BinaryenMinFloat32", "_BinaryenMaxFloat32", "_BinaryenEqFloat32", "_BinaryenNeFloat32", "_BinaryenLtFloat32", "_BinaryenLeFloat32", "_BinaryenGtFloat32", "_BinaryenGeFloat32", "_BinaryenAddFloat64", "_BinaryenSubFloat64", "_BinaryenMulFloat64", "_BinaryenDivFloat64", "_BinaryenCopySignFloat64", "_BinaryenMinFloat64", "_BinaryenMaxFloat64", "_BinaryenEqFloat64", "_BinaryenNeFloat64", "_BinaryenLtFloat64", "_BinaryenLeFloat64", "_BinaryenGtFloat64", "_BinaryenGeFloat64", "_BinaryenPageSize", "_BinaryenCurrentMemory", "_BinaryenGrowMemory", "_BinaryenHasFeature", "_BinaryenBlock", "_BinaryenIf", "_BinaryenLoop", "_BinaryenBreak", "_BinaryenSwitch", "_BinaryenCall", "_BinaryenCallImport", "_BinaryenCallIndirect", "_BinaryenGetLocal", "_BinaryenSetLocal", "_BinaryenTeeLocal", "_BinaryenGetGlobal", "_BinaryenSetGlobal", "_BinaryenLoad", "_BinaryenStore", "_BinaryenConst", "_BinaryenUnary", "_BinaryenBinary", "_BinaryenSelect", "_BinaryenDrop", "_BinaryenReturn", "_BinaryenHost", "_BinaryenNop", "_BinaryenUnreachable", "_BinaryenExpressionPrint", "_BinaryenAddFunction", "_BinaryenAddGlobal", "_BinaryenAddImport", "_BinaryenRemoveImport", "_BinaryenAddExport", "_BinaryenRemoveExport", "_BinaryenSetFunctionTable", "_BinaryenSetMemory", "_BinaryenSetStart", "_BinaryenModuleParse", "_BinaryenModulePrint", "_BinaryenModulePrintAsmjs", "_BinaryenModuleValidate", "_BinaryenModuleOptimize", "_BinaryenModuleRunPasses", "_BinaryenModuleAutoDrop", "_BinaryenModuleWrite", "_BinaryenModuleRead", "_BinaryenModuleInterpret", "_RelooperCreate", "_RelooperAddBlock", "_RelooperAddBranch", "_RelooperAddBlockWithSwitch", "_RelooperAddBranchForSwitch", "_RelooperRenderAndDispose", "_BinaryenSetAPITracing"]' \
149150
-o bin/binaryen${OUT_FILE_SUFFIX}.js \
150151
--pre-js src/js/binaryen.js-pre.js \
151152
--post-js src/js/binaryen.js-post.js

docs/binaryen.js.Markdown

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ Module operations:
3939
* `emitBinary()`: Returns a binary for the module, which you can then compile and run in the browser.
4040
* `emitText()`: Returns a text representation of the module, in s-expression format.
4141
* `validate()`: Validates the module, checking it for correctness.
42-
* `optimize()`: Optimize the module.
42+
* `optimize()`: Runs the standard optimization passes on the module.
43+
* `runPasses(passes)`: Runs the specified passes on the module.
4344
* `autoDrop()`: Automatically inserts `drop` operations. This lets you not worry about dropping when creating your code.
4445
* `interpret()`: Run the module in the Binaryen interpreter (creates the module, and calls the start method). Useful for debugging.
4546
* `dispose()`: Cleans up the module. If the Binaryen object can be garbage-collected anyhow, you don't need to do this, but if it stays around - e.g. if you create multiple `Module`s over time - then you should call this once a `Module` is no longer needed. (As binaryen.js uses compiled C++ code, we can't just rely on normal garbage collection to clean things up internally.)

src/binaryen-c.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,27 @@ void BinaryenModuleOptimize(BinaryenModuleRef module) {
969969
passRunner.run();
970970
}
971971

972+
void BinaryenModuleRunPasses(BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses) {
973+
if (tracing) {
974+
std::cout << " {\n";
975+
std::cout << " const char* passes[] = { ";
976+
for (BinaryenIndex i = 0; i < numPasses; i++) {
977+
if (i > 0) std::cout << ", ";
978+
std::cout << "\"" << passes[i] << "\"";
979+
}
980+
std::cout << " };\n";
981+
std::cout << " BinaryenModuleRunPasses(the_module, passes, " << numPasses << ");\n";
982+
std::cout << " }\n";
983+
}
984+
985+
Module* wasm = (Module*)module;
986+
PassRunner passRunner(wasm);
987+
for (BinaryenIndex i = 0; i < numPasses; i++) {
988+
passRunner.add(passes[i]);
989+
}
990+
passRunner.run();
991+
}
992+
972993
void BinaryenModuleAutoDrop(BinaryenModuleRef module) {
973994
if (tracing) {
974995
std::cout << " BinaryenModuleAutoDrop(the_module);\n";

src/binaryen-c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,9 @@ int BinaryenModuleValidate(BinaryenModuleRef module);
391391
// Run the standard optimization passes on the module.
392392
void BinaryenModuleOptimize(BinaryenModuleRef module);
393393

394+
// Runs the specified passes on the module.
395+
void BinaryenModuleRunPasses(BinaryenModuleRef module, const char **passes, BinaryenIndex numPasses);
396+
394397
// Auto-generate drop() operations where needed. This lets you generate code without
395398
// worrying about where they are needed. (It is more efficient to do it yourself,
396399
// but simpler to use autodrop).

src/js/binaryen.js-post.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,13 @@
847847
this['optimize'] = function() {
848848
return Module['_BinaryenModuleOptimize'](module);
849849
};
850+
this['runPasses'] = function(passes) {
851+
return preserveStack(function() {
852+
return Module['_BinaryenModuleRunPasses'](module, i32sToStack(
853+
passes.map(strToStack)
854+
), passes.length);
855+
});
856+
}
850857
this['autoDrop'] = function() {
851858
return Module['_BinaryenModuleAutoDrop'](module);
852859
};

src/wasm-js.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm2wasm(char *input) {
8080
module->memory.max = pre.memoryGrowth ? Address(Memory::kMaxSize) : module->memory.initial;
8181

8282
if (wasmJSDebug) std::cerr << "wasming...\n";
83-
asm2wasm = new Asm2WasmBuilder(*module, pre, debug, Asm2WasmBuilder::TrapMode::JS, PassOptions(), true /* runJSFFIPass */, false /* TODO: support optimizing? */, false /* TODO: support asm2wasm-i64? */);
83+
asm2wasm = new Asm2WasmBuilder(*module, pre, debug, TrapMode::JS, PassOptions(), true /* runJSFFIPass */, false /* TODO: support optimizing? */, false /* TODO: support asm2wasm-i64? */);
8484
asm2wasm->processAsm(asmjs);
8585
}
8686

test/binaryen.js/kitchen-sink.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ function test_relooper() {
416416

417417
assert(module.validate());
418418

419+
module.runPasses(["precompute"]);
420+
421+
assert(module.validate());
422+
419423
module.optimize();
420424

421425
assert(module.validate());

test/binaryen.js/kitchen-sink.js.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,6 +2901,11 @@ raw:
29012901
)
29022902
)
29032903

2904+
BinaryenModuleValidate(the_module);
2905+
{
2906+
const char* passes[] = { "precompute" };
2907+
BinaryenModuleRunPasses(the_module, passes, 1);
2908+
}
29042909
BinaryenModuleValidate(the_module);
29052910
BinaryenModuleOptimize(the_module);
29062911
BinaryenModuleValidate(the_module);

0 commit comments

Comments
 (0)