@@ -600,34 +600,143 @@ exports.main = function main(argv, options, callback) {
600
600
module . setShrinkLevel ( shrinkLevel ) ;
601
601
module . setDebugInfo ( args . debug ) ;
602
602
603
- var runPasses = [ ] ;
603
+ const runPasses = [ ] ;
604
604
if ( args . runPasses ) {
605
605
if ( typeof args . runPasses === "string" ) {
606
606
args . runPasses = args . runPasses . split ( "," ) ;
607
607
}
608
608
if ( args . runPasses . length ) {
609
609
args . runPasses . forEach ( pass => {
610
- if ( runPasses . indexOf ( pass ) < 0 )
610
+ if ( runPasses . indexOf ( pass = pass . trim ( ) ) < 0 )
611
611
runPasses . push ( pass ) ;
612
612
} ) ;
613
613
}
614
614
}
615
615
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 ) ) ;
622
719
}
623
720
624
- // Run additional passes if requested
625
- if ( runPasses . length ) {
721
+ stats . optimizeTime += measure ( ( ) => {
626
722
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
+ } ) ;
631
740
632
741
// Prepare output
633
742
if ( ! args . noEmit ) {
0 commit comments