@@ -600,34 +600,143 @@ exports.main = function main(argv, options, callback) {
600600 module . setShrinkLevel ( shrinkLevel ) ;
601601 module . setDebugInfo ( args . debug ) ;
602602
603- var runPasses = [ ] ;
603+ const runPasses = [ ] ;
604604 if ( args . runPasses ) {
605605 if ( typeof args . runPasses === "string" ) {
606606 args . runPasses = args . runPasses . split ( "," ) ;
607607 }
608608 if ( args . runPasses . length ) {
609609 args . runPasses . forEach ( pass => {
610- if ( runPasses . indexOf ( pass ) < 0 )
610+ if ( runPasses . indexOf ( pass = pass . trim ( ) ) < 0 )
611611 runPasses . push ( pass ) ;
612612 } ) ;
613613 }
614614 }
615615
616- // Optimize the module if requested
617- if ( optimizeLevel > 0 || shrinkLevel > 0 ) {
618- stats . optimizeCount ++ ;
619- stats . optimizeTime += measure ( ( ) => {
620- module . optimize ( ) ;
621- } ) ;
616+ function doOptimize ( ) {
617+ const hasARC = args . runtime == "half" || args . runtime == "full" ;
618+ const passes = [ ] ;
619+ function add ( pass ) { passes . push ( pass ) ; }
620+
621+ // Optimize the module if requested
622+ if ( optimizeLevel > 0 || shrinkLevel > 0 ) {
623+ // Binaryen's default passes with Post-AssemblyScript passes added.
624+ // see: Binaryen/src/pass.cpp
625+
626+ // PassRunner::addDefaultGlobalOptimizationPrePasses
627+ add ( "duplicate-function-elimination" ) ;
628+
629+ // PassRunner::addDefaultFunctionOptimizationPasses
630+ if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) {
631+ add ( "ssa-nomerge" ) ;
632+ }
633+ if ( optimizeLevel >= 4 ) {
634+ add ( "flatten" ) ;
635+ add ( "local-cse" ) ;
636+ }
637+ // if (hasARC) { // differs
638+ // if (optimizeLevel < 4) {
639+ // add("flatten");
640+ // }
641+ // add("post-assemblyscript");
642+ // }
643+ add ( "dce" ) ;
644+ add ( "remove-unused-brs" ) ;
645+ add ( "remove-unused-names" ) ;
646+ add ( "optimize-instructions" ) ;
647+ if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
648+ add ( "pick-load-signs" ) ;
649+ }
650+ if ( optimizeLevel >= 3 || shrinkLevel >= 2 ) {
651+ add ( "precompute-propagate" ) ;
652+ } else {
653+ add ( "precompute" ) ;
654+ }
655+ if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
656+ add ( "code-pushing" ) ;
657+ }
658+ add ( "simplify-locals-nostructure" ) ;
659+ add ( "vacuum" ) ;
660+ add ( "reorder-locals" ) ;
661+ add ( "remove-unused-brs" ) ;
662+ if ( optimizeLevel >= 3 || shrinkLevel >= 2 ) {
663+ add ( "merge-locals" ) ;
664+ }
665+ add ( "coalesce-locals" ) ;
666+ add ( "simplify-locals" ) ;
667+ add ( "vacuum" ) ;
668+ add ( "reorder-locals" ) ;
669+ add ( "coalesce-locals" ) ;
670+ add ( "reorder-locals" ) ;
671+ add ( "vacuum" ) ;
672+ if ( optimizeLevel >= 3 || shrinkLevel >= 1 ) {
673+ add ( "code-folding" ) ;
674+ }
675+ add ( "merge-blocks" ) ;
676+ add ( "remove-unused-brs" ) ;
677+ add ( "remove-unused-names" ) ;
678+ add ( "merge-blocks" ) ;
679+ if ( optimizeLevel >= 3 || shrinkLevel >= 2 ) {
680+ add ( "precompute-propagate" ) ;
681+ } else {
682+ add ( "precompute" ) ;
683+ }
684+ add ( "optimize-instructions" ) ;
685+ if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
686+ add ( "rse" ) ;
687+ }
688+ // if (hasARC) { // differs
689+ // add("post-assemblyscript-finalize");
690+ // }
691+ add ( "vacuum" ) ;
692+
693+ // PassRunner::addDefaultGlobalOptimizationPostPasses
694+ if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
695+ add ( "dae-optimizing" ) ;
696+ }
697+ if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
698+ add ( "inlining-optimizing" ) ;
699+ }
700+ add ( "duplicate-function-elimination" ) ;
701+ add ( "duplicate-import-elimination" ) ;
702+ if ( optimizeLevel >= 2 || shrinkLevel >= 2 ) {
703+ add ( "simplify-globals-optimizing" ) ;
704+ } else {
705+ add ( "simplify-globals" ) ;
706+ }
707+ add ( "remove-unused-module-elements" ) ;
708+ add ( "memory-packing" ) ;
709+ add ( "directize" ) ;
710+ add ( "inlining-optimizing" ) ; // differs
711+ if ( optimizeLevel >= 2 || shrinkLevel >= 1 ) {
712+ add ( "generate-stack-ir" ) ;
713+ add ( "optimize-stack-ir" ) ;
714+ }
715+ }
716+
717+ // Append additional passes if requested and execute
718+ module . runPasses ( passes . concat ( runPasses ) ) ;
622719 }
623720
624- // Run additional passes if requested
625- if ( runPasses . length ) {
721+ stats . optimizeTime += measure ( ( ) => {
626722 stats . optimizeCount ++ ;
627- stats . optimizeTime += measure ( ( ) => {
628- module . runPasses ( runPasses . map ( pass => pass . trim ( ) ) ) ;
629- } ) ;
630- }
723+ doOptimize ( ) ;
724+ if ( args . converge ) {
725+ let last = module . toBinary ( ) ;
726+ do {
727+ stats . optimizeCount ++ ;
728+ doOptimize ( ) ;
729+ let next = module . toBinary ( ) ;
730+ if ( next . output . length >= last . output . length ) {
731+ if ( next . output . length > last . output . length ) {
732+ stderr . write ( "Last converge was suboptimial." + EOL ) ;
733+ }
734+ break ;
735+ }
736+ last = next ;
737+ } while ( true ) ;
738+ }
739+ } ) ;
631740
632741 // Prepare output
633742 if ( ! args . noEmit ) {
0 commit comments