11open Binaryen ;
22open Grain_utils ;
33
4- // Defaults from https://github.com/WebAssembly/binaryen/blob/version_107 /src/pass.h#L170-L171
4+ // Defaults from https://github.com/WebAssembly/binaryen/blob/version_124 /src/pass.h#L247-L248
55let default_optimize_level = 2 ;
66let default_shrink_level = 1 ;
77
88let has_gc = wasm_mod =>
99 List . mem(Module . Feature . gc, Module . get_features(wasm_mod));
10+ let has_multivalue = wasm_mod =>
11+ List . mem(Module . Feature . multivalue, Module . get_features(wasm_mod));
12+ let has_strings = wasm_mod =>
13+ List . mem(Module . Feature . strings, Module . get_features(wasm_mod));
1014
11- // Translation of https://github.com/WebAssembly/binaryen/blob/version_107 /src/passes/pass.cpp#L546-L566
15+ // Translation of https://github.com/WebAssembly/binaryen/blob/version_124 /src/passes/pass.cpp#L738-L777
1216let default_global_optimization_pre_passes =
1317 (~optimize_level, ~shrink_level, wasm_mod) => {
1418 List . concat([
15- [ Passes . duplicate_function_elimination, Passes . memory_packing] ,
19+ // Removing duplicate functions is fast and saves work later.
20+ [ Passes . duplicate_function_elimination] ,
21+ // Do a global cleanup before anything heavy, as it is fairly fast and can
22+ // save a lot of work if there is a significant amount of dead code.
23+ if (optimize_level >= 2 ) {
24+ [ Passes . remove_unused_module_elements] ;
25+ } else {
26+ [] ;
27+ },
28+ [ Passes . memory_packing] ,
1629 if (optimize_level >= 2 ) {
1730 [ Passes . once_reduction] ;
1831 } else {
1932 [] ;
2033 },
21- if (has_gc(wasm_mod)
22- && /* TODO: getTypeSystem() == TypeSystem::Nominal && */ optimize_level
23- >= 2 ) {
24- [
25- Passes . type_refining,
26- Passes . signature_refining,
27- Passes . global_refining,
28- // Global type optimization can remove fields that are not needed, which can
29- // remove ref.funcs that were once assigned to vtables but are no longer
30- // needed, which can allow more code to be removed globally. After those,
31- // constant field propagation can be more effective.
32- Passes . gto,
33- Passes . remove_unused_module_elements,
34- Passes . cfp,
35- ] ;
34+ if (has_gc(wasm_mod) && optimize_level >= 2 ) {
35+ List . concat([
36+ if (Settings . get_closed_world() ) {
37+ [
38+ Passes . type_refining,
39+ Passes . signature_pruning,
40+ Passes . signature_refining,
41+ ] ;
42+ } else {
43+ [] ;
44+ },
45+ [ Passes . global_refining] ,
46+ if (Settings . get_closed_world() ) {
47+ [
48+ // Global type optimization can remove fields that are not needed, which can
49+ // remove ref.funcs that were once assigned to vtables but are no longer
50+ // needed, which can allow more code to be removed globally. After those,
51+ // constant field propagation can be more effective.
52+ Passes . gto,
53+ ] ;
54+ } else {
55+ [] ;
56+ },
57+ [ Passes . remove_unused_module_elements] ,
58+ if (Settings . get_closed_world() ) {
59+ [
60+ Passes . remove_unused_types,
61+ Passes . cfp,
62+ Passes . gsi,
63+ Passes . abstract_type_refining,
64+ Passes . unsubtyping,
65+ ] ;
66+ } else {
67+ [] ;
68+ },
69+ ] );
3670 } else {
3771 [] ;
3872 },
3973 ] );
4074};
4175
42- // Translation of https://github.com/WebAssembly/binaryen/blob/version_107 /src/passes/pass.cpp#L447-L544
76+ // Translation of https://github.com/WebAssembly/binaryen/blob/version_124 /src/passes/pass.cpp#L626-L736
4377let default_function_optimization_passes =
4478 (~optimize_level, ~shrink_level, wasm_mod) => {
4579 List . concat([
@@ -64,7 +98,7 @@ let default_function_optimization_passes =
6498 // run some amount of simplify-locals first).
6599 Passes . simplify_locals_notee_nostructure,
66100 Passes . local_cse,
67- // TODO: add rereloop etc. here
101+ // TODO(BINARYEN) : add rereloop etc. here
68102 ] ;
69103 } else {
70104 [] ;
@@ -76,6 +110,11 @@ let default_function_optimization_passes =
76110 Passes . remove_unused_names,
77111 Passes . optimize_instructions,
78112 ] ,
113+ if (has_gc(wasm_mod)) {
114+ [ Passes . heap_store_optimization] ;
115+ } else {
116+ [] ;
117+ },
79118 if (optimize_level >= 2 || shrink_level >= 2 ) {
80119 [ Passes . pick_load_signs] ;
81120 } else {
@@ -101,9 +140,19 @@ let default_function_optimization_passes =
101140 } else {
102141 [] ;
103142 },
143+ if (has_multivalue(wasm_mod)) {
144+ [
145+ // Optimize tuples before local opts (as splitting tuples can help local
146+ // opts), but also not too early, as we want to be after
147+ // optimize-instructions at least (which can remove tuple-related things).
148+ Passes . tuple_optimization,
149+ ] ;
150+ } else {
151+ [] ;
152+ },
153+ // don't create if/block return values yet, as coalesce can remove copies that
154+ // that could inhibit
104155 [
105- // don't create if/block return values yet, as coalesce can remove copies that
106- // that could inhibit
107156 Passes . simplify_locals_nostructure,
108157 Passes . vacuum, // previous pass creates garbage
109158 Passes . reorder_locals,
@@ -125,9 +174,10 @@ let default_function_optimization_passes =
125174 },
126175 if (optimize_level > 1 && has_gc(wasm_mod)) {
127176 [
177+ Passes . optimize_casts,
128178 // Coalescing may prevent subtyping (as a coalesced local must have the
129179 // supertype of all those combined into it), so subtype first.
130- // TODO: when optimizing for size, maybe the order should reverse?
180+ // TODO(BINARYEN) : when optimizing for size, maybe the order should reverse?
131181 Passes . local_subtyping,
132182 ] ;
133183 } else {
@@ -165,6 +215,11 @@ let default_function_optimization_passes =
165215 [ Passes . precompute] ;
166216 },
167217 [ Passes . optimize_instructions] ,
218+ if (has_gc(wasm_mod)) {
219+ [ Passes . heap_store_optimization] ;
220+ } else {
221+ [] ;
222+ },
168223 if (optimize_level >= 2 || shrink_level >= 1 ) {
169224 [
170225 Passes . rse // after all coalesce-locals, and before a final vacuum
@@ -176,7 +231,7 @@ let default_function_optimization_passes =
176231 ] );
177232};
178233
179- // Translation of https://github.com/WebAssembly/binaryen/blob/version_107 /src/passes/pass.cpp#L568-L599
234+ // Translation of https://github.com/WebAssembly/binaryen/blob/version_124 /src/passes/pass.cpp#L788-L821
180235let default_global_optimization_post_passes =
181236 (~optimize_level, ~shrink_level, wasm_mod) => {
182237 List . concat([
@@ -206,18 +261,23 @@ let default_global_optimization_post_passes =
206261 } else {
207262 [ Passes . simplify_globals] ;
208263 },
209- [
210- Passes . remove_unused_module_elements,
211- // may allow more inlining/dae/etc., need --converge for that
212- Passes . directize,
213- ] ,
214- // perform Stack IR optimizations here, at the very end of the
215- // optimization pipeline
264+ [ Passes . remove_unused_module_elements] ,
265+ if (optimize_level >= 2 && has_strings(wasm_mod)) {
266+ [
267+ // Gather strings to globals right before reorder-globals, which will then
268+ // sort them properly.
269+ Passes . string_gathering,
270+ ] ;
271+ } else {
272+ [] ;
273+ },
216274 if (optimize_level >= 2 || shrink_level >= 1 ) {
217- [ Passes . generate_stack_ir , Passes . optimize_stack_ir ] ;
275+ [ Passes . reorder_globals ] ;
218276 } else {
219277 [] ;
220278 },
279+ // may allow more inlining/dae/etc., need --converge for that
280+ [ Passes . directize] ,
221281 ] );
222282};
223283
@@ -227,7 +287,7 @@ let optimize =
227287 ~shrink_level= default_shrink_level,
228288 wasm_mod,
229289 ) => {
230- // Translation of https://github.com/WebAssembly/binaryen/blob/version_107 /src/passes/pass.cpp#L441-L445
290+ // Translation of https://github.com/WebAssembly/binaryen/blob/version_124 /src/passes/pass.cpp#L620-L624
231291 let default_optimizations_passes =
232292 List . concat([
233293 default_global_optimization_pre_passes(
0 commit comments