diff options
author | Thomas Lively <tlively@google.com> | 2024-08-16 22:14:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-17 02:14:06 +0000 |
commit | e058bfbdf31c7b59df8ab62a9ebaedac45521c12 (patch) | |
tree | ffdb01a6e5f76057a6f654c2df29f0c6e551d276 /test | |
parent | 95a4d5de6f65b35a64caf014c2f7febb8a799542 (diff) | |
download | binaryen-e058bfbdf31c7b59df8ab62a9ebaedac45521c12.tar.gz binaryen-e058bfbdf31c7b59df8ab62a9ebaedac45521c12.tar.bz2 binaryen-e058bfbdf31c7b59df8ab62a9ebaedac45521c12.zip |
Add a pass for minimizing recursion groups (#6832)
Most of our type optimization passes emit all non-public types as a
single large rec group, which trivially ensures that different types
remain different, even if they are optimized to have the same structure.
Usually emitting a single large rec group is fine, but it also means
that if the module is split, all of the types will need to be repeated
in all of the split modules. To better support this use case, add a pass
that can split the large rec group back into minimal rec groups, taking
care to preserve separate type identities by emitting different
permutations of the same group where possible or by inserting unused
brand types to differentiate them.
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/help/wasm-metadce.test | 3 | ||||
-rw-r--r-- | test/lit/help/wasm-opt.test | 3 | ||||
-rw-r--r-- | test/lit/help/wasm2js.test | 3 | ||||
-rw-r--r-- | test/lit/passes/minimize-rec-groups-brands.wast | 1378 | ||||
-rw-r--r-- | test/lit/passes/minimize-rec-groups.wast | 486 |
5 files changed, 1873 insertions, 0 deletions
diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 8a2107ca7..c40f2e22b 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -269,6 +269,9 @@ ;; CHECK-NEXT: the minified ones, and minifies ;; CHECK-NEXT: the modules as well ;; CHECK-NEXT: +;; CHECK-NEXT: --minimize-rec-groups Split types into minimal +;; CHECK-NEXT: recursion groups +;; CHECK-NEXT: ;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that ;; CHECK-NEXT: asyncify imports always unwind, ;; CHECK-NEXT: and we never rewind diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index a48b8e303..a1df2640a 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -278,6 +278,9 @@ ;; CHECK-NEXT: the minified ones, and minifies ;; CHECK-NEXT: the modules as well ;; CHECK-NEXT: +;; CHECK-NEXT: --minimize-rec-groups Split types into minimal +;; CHECK-NEXT: recursion groups +;; CHECK-NEXT: ;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that ;; CHECK-NEXT: asyncify imports always unwind, ;; CHECK-NEXT: and we never rewind diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 0b87ad0aa..beefdbbd7 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -232,6 +232,9 @@ ;; CHECK-NEXT: the minified ones, and minifies ;; CHECK-NEXT: the modules as well ;; CHECK-NEXT: +;; CHECK-NEXT: --minimize-rec-groups Split types into minimal +;; CHECK-NEXT: recursion groups +;; CHECK-NEXT: ;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that ;; CHECK-NEXT: asyncify imports always unwind, ;; CHECK-NEXT: and we never rewind diff --git a/test/lit/passes/minimize-rec-groups-brands.wast b/test/lit/passes/minimize-rec-groups-brands.wast new file mode 100644 index 000000000..861f88705 --- /dev/null +++ b/test/lit/passes/minimize-rec-groups-brands.wast @@ -0,0 +1,1378 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: wasm-opt %s -all --minimize-rec-groups -S -o - | filecheck %s + +;; Check that brands increment correctly once we get into structs with multiple +;; fields. This requires very many duplicate SCCs. + +(module + (rec + ;; CHECK: (type $0 (struct)) + (type $0 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $10 (struct)) + + ;; CHECK: (type $200 (array (mut i32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $201 (array i32)) + + ;; CHECK: (type $11 (struct)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $12 (struct)) + + ;; CHECK: (type $204 (array i32)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $205 (array (mut i64))) + + ;; CHECK: (type $13 (struct)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $14 (struct)) + + ;; CHECK: (type $208 (array (mut i64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $209 (array i64)) + + ;; CHECK: (type $15 (struct)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $16 (struct)) + + ;; CHECK: (type $212 (array i64)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $213 (array (mut f32))) + + ;; CHECK: (type $17 (struct)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $18 (struct)) + + ;; CHECK: (type $216 (array (mut f32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $217 (array f32)) + + ;; CHECK: (type $19 (struct)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $219 (array (mut i8))) + + ;; CHECK: (type $1 (struct)) + (type $1 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (struct)) + (type $2 (struct)) + ;; CHECK: (type $222 (array (mut i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $223 (array i8)) + + ;; CHECK: (type $3 (struct)) + (type $3 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $4 (struct)) + (type $4 (struct)) + ;; CHECK: (type $226 (array i8)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $227 (array (mut i16))) + + ;; CHECK: (type $5 (struct)) + (type $5 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $6 (struct)) + (type $6 (struct)) + ;; CHECK: (type $230 (array (mut i16))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $231 (array i16)) + + ;; CHECK: (type $7 (struct)) + (type $7 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $8 (struct)) + (type $8 (struct)) + ;; CHECK: (type $234 (array i16)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $235 (array (mut i32))) + + ;; CHECK: (type $9 (struct)) + (type $9 (struct)) + (type $10 (struct)) + (type $11 (struct)) + (type $12 (struct)) + (type $13 (struct)) + (type $14 (struct)) + (type $15 (struct)) + (type $16 (struct)) + (type $17 (struct)) + (type $18 (struct)) + (type $19 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $20 (struct)) + (type $20 (struct)) + ;; CHECK: (type $238 (array f32)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $239 (array (mut f64))) + + ;; CHECK: (type $21 (struct)) + (type $21 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $22 (struct)) + (type $22 (struct)) + ;; CHECK: (type $242 (array (mut f64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $243 (array f64)) + + ;; CHECK: (type $23 (struct)) + (type $23 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $24 (struct)) + (type $24 (struct)) + ;; CHECK: (type $246 (array f64)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $247 (array (mut anyref))) + + ;; CHECK: (type $25 (struct)) + (type $25 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $26 (struct)) + (type $26 (struct)) + ;; CHECK: (type $250 (array (mut anyref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $251 (array anyref)) + + ;; CHECK: (type $27 (struct)) + (type $27 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $28 (struct)) + (type $28 (struct)) + ;; CHECK: (type $254 (array anyref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $255 (array (mut funcref))) + + ;; CHECK: (type $29 (struct)) + (type $29 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $30 (struct)) + (type $30 (struct)) + ;; CHECK: (type $258 (array (mut funcref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $259 (array funcref)) + + ;; CHECK: (type $31 (struct)) + (type $31 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $32 (struct)) + (type $32 (struct)) + ;; CHECK: (type $262 (array funcref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $263 (array (mut externref))) + + ;; CHECK: (type $33 (struct)) + (type $33 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $34 (struct)) + (type $34 (struct)) + ;; CHECK: (type $266 (array (mut externref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $267 (array externref)) + + ;; CHECK: (type $35 (struct)) + (type $35 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $36 (struct)) + (type $36 (struct)) + ;; CHECK: (type $270 (array externref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $271 (array (mut nullref))) + + ;; CHECK: (type $37 (struct)) + (type $37 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $38 (struct)) + (type $38 (struct)) + ;; CHECK: (type $274 (array (mut nullref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $275 (array nullref)) + + ;; CHECK: (type $39 (struct)) + (type $39 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $40 (struct)) + (type $40 (struct)) + ;; CHECK: (type $278 (array nullref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $279 (array (mut nullfuncref))) + + ;; CHECK: (type $41 (struct)) + (type $41 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $42 (struct)) + (type $42 (struct)) + ;; CHECK: (type $282 (array (mut nullfuncref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $283 (array nullfuncref)) + + ;; CHECK: (type $43 (struct)) + (type $43 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $44 (struct)) + (type $44 (struct)) + ;; CHECK: (type $286 (array nullfuncref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $287 (array (mut nullexternref))) + + ;; CHECK: (type $45 (struct)) + (type $45 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $46 (struct)) + (type $46 (struct)) + ;; CHECK: (type $290 (array (mut nullexternref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $291 (array nullexternref)) + + ;; CHECK: (type $47 (struct)) + (type $47 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $48 (struct)) + (type $48 (struct)) + ;; CHECK: (type $294 (array nullexternref)) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $295 (array (mut (ref any)))) + + ;; CHECK: (type $49 (struct)) + (type $49 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $50 (struct)) + (type $50 (struct)) + ;; CHECK: (type $298 (array (mut (ref any)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $299 (array (ref any))) + + ;; CHECK: (type $51 (struct)) + (type $51 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $52 (struct)) + (type $52 (struct)) + ;; CHECK: (type $302 (array (ref any))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $303 (array (mut (ref func)))) + + ;; CHECK: (type $53 (struct)) + (type $53 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $54 (struct)) + (type $54 (struct)) + ;; CHECK: (type $306 (array (mut (ref func)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $307 (array (ref func))) + + ;; CHECK: (type $55 (struct)) + (type $55 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $56 (struct)) + (type $56 (struct)) + ;; CHECK: (type $310 (array (ref func))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $311 (array (mut (ref extern)))) + + ;; CHECK: (type $57 (struct)) + (type $57 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $58 (struct)) + (type $58 (struct)) + ;; CHECK: (type $314 (array (mut (ref extern)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $315 (array (ref extern))) + + ;; CHECK: (type $59 (struct)) + (type $59 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $60 (struct)) + (type $60 (struct)) + ;; CHECK: (type $318 (array (ref extern))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $319 (array (mut (ref none)))) + + ;; CHECK: (type $61 (struct)) + (type $61 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $62 (struct)) + (type $62 (struct)) + ;; CHECK: (type $322 (array (mut (ref none)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $323 (array (ref none))) + + ;; CHECK: (type $63 (struct)) + (type $63 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $64 (struct)) + (type $64 (struct)) + ;; CHECK: (type $326 (array (ref none))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $327 (array (mut (ref nofunc)))) + + ;; CHECK: (type $65 (struct)) + (type $65 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $66 (struct)) + (type $66 (struct)) + ;; CHECK: (type $330 (array (mut (ref nofunc)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $331 (array (ref nofunc))) + + ;; CHECK: (type $67 (struct)) + (type $67 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $68 (struct)) + (type $68 (struct)) + ;; CHECK: (type $334 (array (ref nofunc))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $335 (array (mut (ref noextern)))) + + ;; CHECK: (type $69 (struct)) + (type $69 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $70 (struct)) + (type $70 (struct)) + ;; CHECK: (type $338 (array (mut (ref noextern)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $339 (array (ref noextern))) + + ;; CHECK: (type $71 (struct)) + (type $71 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $72 (struct)) + (type $72 (struct)) + ;; CHECK: (type $342 (array (ref noextern))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $343 (struct (field (mut i8)))) + + ;; CHECK: (type $73 (struct)) + (type $73 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $74 (struct)) + (type $74 (struct)) + ;; CHECK: (type $346 (struct (field (mut i8)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $347 (struct (field i8))) + + ;; CHECK: (type $75 (struct)) + (type $75 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $76 (struct)) + (type $76 (struct)) + ;; CHECK: (type $350 (struct (field i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $351 (struct (field (mut i16)))) + + ;; CHECK: (type $77 (struct)) + (type $77 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $78 (struct)) + (type $78 (struct)) + ;; CHECK: (type $354 (struct (field (mut i16)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $355 (struct (field i16))) + + ;; CHECK: (type $79 (struct)) + (type $79 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $80 (struct)) + (type $80 (struct)) + ;; CHECK: (type $358 (struct (field i16))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $359 (struct (field (mut i32)))) + + ;; CHECK: (type $81 (struct)) + (type $81 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $82 (struct)) + (type $82 (struct)) + ;; CHECK: (type $362 (struct (field (mut i32)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $363 (struct (field i32))) + + ;; CHECK: (type $83 (struct)) + (type $83 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $84 (struct)) + (type $84 (struct)) + ;; CHECK: (type $366 (struct (field i32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $367 (struct (field (mut i64)))) + + ;; CHECK: (type $85 (struct)) + (type $85 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $86 (struct)) + (type $86 (struct)) + ;; CHECK: (type $370 (struct (field (mut i64)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $371 (struct (field i64))) + + ;; CHECK: (type $87 (struct)) + (type $87 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $88 (struct)) + (type $88 (struct)) + ;; CHECK: (type $374 (struct (field i64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $375 (struct (field (mut f32)))) + + ;; CHECK: (type $89 (struct)) + (type $89 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $90 (struct)) + (type $90 (struct)) + ;; CHECK: (type $378 (struct (field (mut f32)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $379 (struct (field f32))) + + ;; CHECK: (type $91 (struct)) + (type $91 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $92 (struct)) + (type $92 (struct)) + ;; CHECK: (type $382 (struct (field f32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $383 (struct (field (mut f64)))) + + ;; CHECK: (type $93 (struct)) + (type $93 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $94 (struct)) + (type $94 (struct)) + ;; CHECK: (type $386 (struct (field (mut f64)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $387 (struct (field f64))) + + ;; CHECK: (type $95 (struct)) + (type $95 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $96 (struct)) + (type $96 (struct)) + ;; CHECK: (type $390 (struct (field f64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $391 (struct (field (mut anyref)))) + + ;; CHECK: (type $97 (struct)) + (type $97 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $98 (struct)) + (type $98 (struct)) + ;; CHECK: (type $394 (struct (field (mut anyref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $395 (struct (field anyref))) + + ;; CHECK: (type $99 (struct)) + (type $99 (struct)) + (type $100 (struct)) + (type $101 (struct)) + (type $102 (struct)) + (type $103 (struct)) + (type $104 (struct)) + (type $105 (struct)) + (type $106 (struct)) + (type $107 (struct)) + (type $108 (struct)) + (type $109 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $110 (struct)) + (type $110 (struct)) + ;; CHECK: (type $398 (struct (field anyref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $399 (struct (field (mut funcref)))) + + ;; CHECK: (type $111 (struct)) + (type $111 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $112 (struct)) + (type $112 (struct)) + ;; CHECK: (type $402 (struct (field (mut funcref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $403 (struct (field funcref))) + + ;; CHECK: (type $113 (struct)) + (type $113 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $114 (struct)) + (type $114 (struct)) + ;; CHECK: (type $406 (struct (field funcref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $407 (struct (field (mut externref)))) + + ;; CHECK: (type $115 (struct)) + (type $115 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $116 (struct)) + (type $116 (struct)) + ;; CHECK: (type $410 (struct (field (mut externref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $411 (struct (field externref))) + + ;; CHECK: (type $117 (struct)) + (type $117 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $118 (struct)) + (type $118 (struct)) + ;; CHECK: (type $414 (struct (field externref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $415 (struct (field (mut nullref)))) + + ;; CHECK: (type $119 (struct)) + (type $119 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $120 (struct)) + (type $120 (struct)) + ;; CHECK: (type $418 (struct (field (mut nullref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $419 (struct (field nullref))) + + ;; CHECK: (type $121 (struct)) + (type $121 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $122 (struct)) + (type $122 (struct)) + ;; CHECK: (type $422 (struct (field nullref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $423 (struct (field (mut nullfuncref)))) + + ;; CHECK: (type $123 (struct)) + (type $123 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $124 (struct)) + (type $124 (struct)) + ;; CHECK: (type $426 (struct (field (mut nullfuncref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $427 (struct (field nullfuncref))) + + ;; CHECK: (type $125 (struct)) + (type $125 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $126 (struct)) + (type $126 (struct)) + ;; CHECK: (type $430 (struct (field nullfuncref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $431 (struct (field (mut nullexternref)))) + + ;; CHECK: (type $127 (struct)) + (type $127 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $128 (struct)) + (type $128 (struct)) + ;; CHECK: (type $434 (struct (field (mut nullexternref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $435 (struct (field nullexternref))) + + ;; CHECK: (type $129 (struct)) + (type $129 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $130 (struct)) + (type $130 (struct)) + ;; CHECK: (type $438 (struct (field nullexternref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $439 (struct (field (mut (ref any))))) + + ;; CHECK: (type $131 (struct)) + (type $131 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $132 (struct)) + (type $132 (struct)) + ;; CHECK: (type $442 (struct (field (mut (ref any))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $443 (struct (field (ref any)))) + + ;; CHECK: (type $133 (struct)) + (type $133 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $134 (struct)) + (type $134 (struct)) + ;; CHECK: (type $446 (struct (field (ref any)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $447 (struct (field (mut (ref func))))) + + ;; CHECK: (type $135 (struct)) + (type $135 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $136 (struct)) + (type $136 (struct)) + ;; CHECK: (type $450 (struct (field (mut (ref func))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $451 (struct (field (ref func)))) + + ;; CHECK: (type $137 (struct)) + (type $137 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $138 (struct)) + (type $138 (struct)) + ;; CHECK: (type $454 (struct (field (ref func)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $455 (struct (field (mut (ref extern))))) + + ;; CHECK: (type $139 (struct)) + (type $139 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $140 (struct)) + (type $140 (struct)) + ;; CHECK: (type $458 (struct (field (mut (ref extern))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $459 (struct (field (ref extern)))) + + ;; CHECK: (type $141 (struct)) + (type $141 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $142 (struct)) + (type $142 (struct)) + ;; CHECK: (type $462 (struct (field (ref extern)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $463 (struct (field (mut (ref none))))) + + ;; CHECK: (type $143 (struct)) + (type $143 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $144 (struct)) + (type $144 (struct)) + ;; CHECK: (type $466 (struct (field (mut (ref none))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $467 (struct (field (ref none)))) + + ;; CHECK: (type $145 (struct)) + (type $145 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $146 (struct)) + (type $146 (struct)) + ;; CHECK: (type $470 (struct (field (ref none)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $471 (struct (field (mut (ref nofunc))))) + + ;; CHECK: (type $147 (struct)) + (type $147 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $148 (struct)) + (type $148 (struct)) + ;; CHECK: (type $474 (struct (field (mut (ref nofunc))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $475 (struct (field (ref nofunc)))) + + ;; CHECK: (type $149 (struct)) + (type $149 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $150 (struct)) + (type $150 (struct)) + ;; CHECK: (type $478 (struct (field (ref nofunc)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $479 (struct (field (mut (ref noextern))))) + + ;; CHECK: (type $151 (struct)) + (type $151 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $152 (struct)) + (type $152 (struct)) + ;; CHECK: (type $482 (struct (field (mut (ref noextern))))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $483 (struct (field (ref noextern)))) + + ;; CHECK: (type $153 (struct)) + (type $153 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $154 (struct)) + (type $154 (struct)) + ;; CHECK: (type $486 (struct (field (ref noextern)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $487 (struct (field (mut i8)) (field (mut i8)))) + + ;; CHECK: (type $155 (struct)) + (type $155 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $156 (struct)) + (type $156 (struct)) + ;; CHECK: (type $490 (struct (field (mut i8)) (field (mut i8)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $491 (struct (field (mut i8)) (field i8))) + + ;; CHECK: (type $157 (struct)) + (type $157 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $158 (struct)) + (type $158 (struct)) + ;; CHECK: (type $494 (struct (field (mut i8)) (field i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $495 (struct (field (mut i8)) (field (mut i16)))) + + ;; CHECK: (type $159 (struct)) + (type $159 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $160 (struct)) + (type $160 (struct)) + ;; CHECK: (type $498 (struct (field (mut i8)) (field (mut i16)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $499 (struct (field (mut i8)) (field i16))) + + ;; CHECK: (type $161 (struct)) + (type $161 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $162 (struct)) + (type $162 (struct)) + ;; CHECK: (type $502 (struct (field (mut i8)) (field i16))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $503 (struct (field (mut i8)) (field (mut i32)))) + + ;; CHECK: (type $163 (struct)) + (type $163 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $164 (struct)) + (type $164 (struct)) + ;; CHECK: (type $506 (struct (field (mut i8)) (field (mut i32)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $507 (struct (field (mut i8)) (field i32))) + + ;; CHECK: (type $165 (struct)) + (type $165 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $166 (struct)) + (type $166 (struct)) + ;; CHECK: (type $510 (struct (field (mut i8)) (field i32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $511 (struct (field (mut i8)) (field (mut i64)))) + + ;; CHECK: (type $167 (struct)) + (type $167 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $168 (struct)) + (type $168 (struct)) + ;; CHECK: (type $514 (struct (field (mut i8)) (field (mut i64)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $515 (struct (field (mut i8)) (field i64))) + + ;; CHECK: (type $169 (struct)) + (type $169 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $170 (struct)) + (type $170 (struct)) + ;; CHECK: (type $518 (struct (field (mut i8)) (field i64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $519 (struct (field (mut i8)) (field (mut f32)))) + + ;; CHECK: (type $171 (struct)) + (type $171 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $172 (struct)) + (type $172 (struct)) + ;; CHECK: (type $522 (struct (field (mut i8)) (field (mut f32)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $523 (struct (field (mut i8)) (field f32))) + + ;; CHECK: (type $173 (struct)) + (type $173 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $174 (struct)) + (type $174 (struct)) + ;; CHECK: (type $526 (struct (field (mut i8)) (field f32))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $527 (struct (field (mut i8)) (field (mut f64)))) + + ;; CHECK: (type $175 (struct)) + (type $175 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $176 (struct)) + (type $176 (struct)) + ;; CHECK: (type $530 (struct (field (mut i8)) (field (mut f64)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $531 (struct (field (mut i8)) (field f64))) + + ;; CHECK: (type $177 (struct)) + (type $177 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $178 (struct)) + (type $178 (struct)) + ;; CHECK: (type $534 (struct (field (mut i8)) (field f64))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $535 (struct (field (mut i8)) (field (mut anyref)))) + + ;; CHECK: (type $179 (struct)) + (type $179 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $180 (struct)) + (type $180 (struct)) + ;; CHECK: (type $538 (struct (field (mut i8)) (field (mut anyref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $539 (struct (field (mut i8)) (field anyref))) + + ;; CHECK: (type $181 (struct)) + (type $181 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $182 (struct)) + (type $182 (struct)) + ;; CHECK: (type $542 (struct (field (mut i8)) (field anyref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $543 (struct (field (mut i8)) (field (mut funcref)))) + + ;; CHECK: (type $183 (struct)) + (type $183 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $184 (struct)) + (type $184 (struct)) + ;; CHECK: (type $546 (struct (field (mut i8)) (field (mut funcref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $547 (struct (field (mut i8)) (field funcref))) + + ;; CHECK: (type $185 (struct)) + (type $185 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $186 (struct)) + (type $186 (struct)) + ;; CHECK: (type $550 (struct (field (mut i8)) (field funcref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $551 (struct (field (mut i8)) (field (mut externref)))) + + ;; CHECK: (type $187 (struct)) + (type $187 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $188 (struct)) + (type $188 (struct)) + ;; CHECK: (type $554 (struct (field (mut i8)) (field (mut externref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $555 (struct (field (mut i8)) (field externref))) + + ;; CHECK: (type $189 (struct)) + (type $189 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $190 (struct)) + (type $190 (struct)) + ;; CHECK: (type $558 (struct (field (mut i8)) (field externref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $559 (struct (field (mut i8)) (field (mut nullref)))) + + ;; CHECK: (type $191 (struct)) + (type $191 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $192 (struct)) + (type $192 (struct)) + ;; CHECK: (type $562 (struct (field (mut i8)) (field (mut nullref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $563 (struct (field (mut i8)) (field nullref))) + + ;; CHECK: (type $193 (struct)) + (type $193 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $194 (struct)) + (type $194 (struct)) + ;; CHECK: (type $566 (struct (field (mut i8)) (field nullref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $567 (struct (field (mut i8)) (field (mut nullfuncref)))) + + ;; CHECK: (type $195 (struct)) + (type $195 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $196 (struct)) + (type $196 (struct)) + ;; CHECK: (type $570 (struct (field (mut i8)) (field (mut nullfuncref)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $571 (struct (field (mut i8)) (field nullfuncref))) + + ;; CHECK: (type $197 (struct)) + (type $197 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $198 (struct)) + (type $198 (struct)) + ;; CHECK: (type $574 (struct (field (mut i8)) (field nullfuncref))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $575 (struct (field (mut i8)) (field (mut nullexternref)))) + + ;; CHECK: (type $199 (struct)) + (type $199 (struct)) + ) + + ;; CHECK: (global $0 (ref null $0) (ref.null none)) + (global $0 (ref null $0) (ref.null none)) + ;; CHECK: (global $1 (ref null $1) (ref.null none)) + (global $1 (ref null $1) (ref.null none)) + ;; CHECK: (global $2 (ref null $2) (ref.null none)) + (global $2 (ref null $2) (ref.null none)) + ;; CHECK: (global $3 (ref null $3) (ref.null none)) + (global $3 (ref null $3) (ref.null none)) + ;; CHECK: (global $4 (ref null $4) (ref.null none)) + (global $4 (ref null $4) (ref.null none)) + ;; CHECK: (global $5 (ref null $5) (ref.null none)) + (global $5 (ref null $5) (ref.null none)) + ;; CHECK: (global $6 (ref null $6) (ref.null none)) + (global $6 (ref null $6) (ref.null none)) + ;; CHECK: (global $7 (ref null $7) (ref.null none)) + (global $7 (ref null $7) (ref.null none)) + ;; CHECK: (global $8 (ref null $8) (ref.null none)) + (global $8 (ref null $8) (ref.null none)) + ;; CHECK: (global $9 (ref null $9) (ref.null none)) + (global $9 (ref null $9) (ref.null none)) + ;; CHECK: (global $10 (ref null $10) (ref.null none)) + (global $10 (ref null $10) (ref.null none)) + ;; CHECK: (global $11 (ref null $11) (ref.null none)) + (global $11 (ref null $11) (ref.null none)) + ;; CHECK: (global $12 (ref null $12) (ref.null none)) + (global $12 (ref null $12) (ref.null none)) + ;; CHECK: (global $13 (ref null $13) (ref.null none)) + (global $13 (ref null $13) (ref.null none)) + ;; CHECK: (global $14 (ref null $14) (ref.null none)) + (global $14 (ref null $14) (ref.null none)) + ;; CHECK: (global $15 (ref null $15) (ref.null none)) + (global $15 (ref null $15) (ref.null none)) + ;; CHECK: (global $16 (ref null $16) (ref.null none)) + (global $16 (ref null $16) (ref.null none)) + ;; CHECK: (global $17 (ref null $17) (ref.null none)) + (global $17 (ref null $17) (ref.null none)) + ;; CHECK: (global $18 (ref null $18) (ref.null none)) + (global $18 (ref null $18) (ref.null none)) + ;; CHECK: (global $19 (ref null $19) (ref.null none)) + (global $19 (ref null $19) (ref.null none)) + ;; CHECK: (global $20 (ref null $20) (ref.null none)) + (global $20 (ref null $20) (ref.null none)) + ;; CHECK: (global $21 (ref null $21) (ref.null none)) + (global $21 (ref null $21) (ref.null none)) + ;; CHECK: (global $22 (ref null $22) (ref.null none)) + (global $22 (ref null $22) (ref.null none)) + ;; CHECK: (global $23 (ref null $23) (ref.null none)) + (global $23 (ref null $23) (ref.null none)) + ;; CHECK: (global $24 (ref null $24) (ref.null none)) + (global $24 (ref null $24) (ref.null none)) + ;; CHECK: (global $25 (ref null $25) (ref.null none)) + (global $25 (ref null $25) (ref.null none)) + ;; CHECK: (global $26 (ref null $26) (ref.null none)) + (global $26 (ref null $26) (ref.null none)) + ;; CHECK: (global $27 (ref null $27) (ref.null none)) + (global $27 (ref null $27) (ref.null none)) + ;; CHECK: (global $28 (ref null $28) (ref.null none)) + (global $28 (ref null $28) (ref.null none)) + ;; CHECK: (global $29 (ref null $29) (ref.null none)) + (global $29 (ref null $29) (ref.null none)) + ;; CHECK: (global $30 (ref null $30) (ref.null none)) + (global $30 (ref null $30) (ref.null none)) + ;; CHECK: (global $31 (ref null $31) (ref.null none)) + (global $31 (ref null $31) (ref.null none)) + ;; CHECK: (global $32 (ref null $32) (ref.null none)) + (global $32 (ref null $32) (ref.null none)) + ;; CHECK: (global $33 (ref null $33) (ref.null none)) + (global $33 (ref null $33) (ref.null none)) + ;; CHECK: (global $34 (ref null $34) (ref.null none)) + (global $34 (ref null $34) (ref.null none)) + ;; CHECK: (global $35 (ref null $35) (ref.null none)) + (global $35 (ref null $35) (ref.null none)) + ;; CHECK: (global $36 (ref null $36) (ref.null none)) + (global $36 (ref null $36) (ref.null none)) + ;; CHECK: (global $37 (ref null $37) (ref.null none)) + (global $37 (ref null $37) (ref.null none)) + ;; CHECK: (global $38 (ref null $38) (ref.null none)) + (global $38 (ref null $38) (ref.null none)) + ;; CHECK: (global $39 (ref null $39) (ref.null none)) + (global $39 (ref null $39) (ref.null none)) + ;; CHECK: (global $40 (ref null $40) (ref.null none)) + (global $40 (ref null $40) (ref.null none)) + ;; CHECK: (global $41 (ref null $41) (ref.null none)) + (global $41 (ref null $41) (ref.null none)) + ;; CHECK: (global $42 (ref null $42) (ref.null none)) + (global $42 (ref null $42) (ref.null none)) + ;; CHECK: (global $43 (ref null $43) (ref.null none)) + (global $43 (ref null $43) (ref.null none)) + ;; CHECK: (global $44 (ref null $44) (ref.null none)) + (global $44 (ref null $44) (ref.null none)) + ;; CHECK: (global $45 (ref null $45) (ref.null none)) + (global $45 (ref null $45) (ref.null none)) + ;; CHECK: (global $46 (ref null $46) (ref.null none)) + (global $46 (ref null $46) (ref.null none)) + ;; CHECK: (global $47 (ref null $47) (ref.null none)) + (global $47 (ref null $47) (ref.null none)) + ;; CHECK: (global $48 (ref null $48) (ref.null none)) + (global $48 (ref null $48) (ref.null none)) + ;; CHECK: (global $49 (ref null $49) (ref.null none)) + (global $49 (ref null $49) (ref.null none)) + ;; CHECK: (global $50 (ref null $50) (ref.null none)) + (global $50 (ref null $50) (ref.null none)) + ;; CHECK: (global $51 (ref null $51) (ref.null none)) + (global $51 (ref null $51) (ref.null none)) + ;; CHECK: (global $52 (ref null $52) (ref.null none)) + (global $52 (ref null $52) (ref.null none)) + ;; CHECK: (global $53 (ref null $53) (ref.null none)) + (global $53 (ref null $53) (ref.null none)) + ;; CHECK: (global $54 (ref null $54) (ref.null none)) + (global $54 (ref null $54) (ref.null none)) + ;; CHECK: (global $55 (ref null $55) (ref.null none)) + (global $55 (ref null $55) (ref.null none)) + ;; CHECK: (global $56 (ref null $56) (ref.null none)) + (global $56 (ref null $56) (ref.null none)) + ;; CHECK: (global $57 (ref null $57) (ref.null none)) + (global $57 (ref null $57) (ref.null none)) + ;; CHECK: (global $58 (ref null $58) (ref.null none)) + (global $58 (ref null $58) (ref.null none)) + ;; CHECK: (global $59 (ref null $59) (ref.null none)) + (global $59 (ref null $59) (ref.null none)) + ;; CHECK: (global $60 (ref null $60) (ref.null none)) + (global $60 (ref null $60) (ref.null none)) + ;; CHECK: (global $61 (ref null $61) (ref.null none)) + (global $61 (ref null $61) (ref.null none)) + ;; CHECK: (global $62 (ref null $62) (ref.null none)) + (global $62 (ref null $62) (ref.null none)) + ;; CHECK: (global $63 (ref null $63) (ref.null none)) + (global $63 (ref null $63) (ref.null none)) + ;; CHECK: (global $64 (ref null $64) (ref.null none)) + (global $64 (ref null $64) (ref.null none)) + ;; CHECK: (global $65 (ref null $65) (ref.null none)) + (global $65 (ref null $65) (ref.null none)) + ;; CHECK: (global $66 (ref null $66) (ref.null none)) + (global $66 (ref null $66) (ref.null none)) + ;; CHECK: (global $67 (ref null $67) (ref.null none)) + (global $67 (ref null $67) (ref.null none)) + ;; CHECK: (global $68 (ref null $68) (ref.null none)) + (global $68 (ref null $68) (ref.null none)) + ;; CHECK: (global $69 (ref null $69) (ref.null none)) + (global $69 (ref null $69) (ref.null none)) + ;; CHECK: (global $70 (ref null $70) (ref.null none)) + (global $70 (ref null $70) (ref.null none)) + ;; CHECK: (global $71 (ref null $71) (ref.null none)) + (global $71 (ref null $71) (ref.null none)) + ;; CHECK: (global $72 (ref null $72) (ref.null none)) + (global $72 (ref null $72) (ref.null none)) + ;; CHECK: (global $73 (ref null $73) (ref.null none)) + (global $73 (ref null $73) (ref.null none)) + ;; CHECK: (global $74 (ref null $74) (ref.null none)) + (global $74 (ref null $74) (ref.null none)) + ;; CHECK: (global $75 (ref null $75) (ref.null none)) + (global $75 (ref null $75) (ref.null none)) + ;; CHECK: (global $76 (ref null $76) (ref.null none)) + (global $76 (ref null $76) (ref.null none)) + ;; CHECK: (global $77 (ref null $77) (ref.null none)) + (global $77 (ref null $77) (ref.null none)) + ;; CHECK: (global $78 (ref null $78) (ref.null none)) + (global $78 (ref null $78) (ref.null none)) + ;; CHECK: (global $79 (ref null $79) (ref.null none)) + (global $79 (ref null $79) (ref.null none)) + ;; CHECK: (global $80 (ref null $80) (ref.null none)) + (global $80 (ref null $80) (ref.null none)) + ;; CHECK: (global $81 (ref null $81) (ref.null none)) + (global $81 (ref null $81) (ref.null none)) + ;; CHECK: (global $82 (ref null $82) (ref.null none)) + (global $82 (ref null $82) (ref.null none)) + ;; CHECK: (global $83 (ref null $83) (ref.null none)) + (global $83 (ref null $83) (ref.null none)) + ;; CHECK: (global $84 (ref null $84) (ref.null none)) + (global $84 (ref null $84) (ref.null none)) + ;; CHECK: (global $85 (ref null $85) (ref.null none)) + (global $85 (ref null $85) (ref.null none)) + ;; CHECK: (global $86 (ref null $86) (ref.null none)) + (global $86 (ref null $86) (ref.null none)) + ;; CHECK: (global $87 (ref null $87) (ref.null none)) + (global $87 (ref null $87) (ref.null none)) + ;; CHECK: (global $88 (ref null $88) (ref.null none)) + (global $88 (ref null $88) (ref.null none)) + ;; CHECK: (global $89 (ref null $89) (ref.null none)) + (global $89 (ref null $89) (ref.null none)) + ;; CHECK: (global $90 (ref null $90) (ref.null none)) + (global $90 (ref null $90) (ref.null none)) + ;; CHECK: (global $91 (ref null $91) (ref.null none)) + (global $91 (ref null $91) (ref.null none)) + ;; CHECK: (global $92 (ref null $92) (ref.null none)) + (global $92 (ref null $92) (ref.null none)) + ;; CHECK: (global $93 (ref null $93) (ref.null none)) + (global $93 (ref null $93) (ref.null none)) + ;; CHECK: (global $94 (ref null $94) (ref.null none)) + (global $94 (ref null $94) (ref.null none)) + ;; CHECK: (global $95 (ref null $95) (ref.null none)) + (global $95 (ref null $95) (ref.null none)) + ;; CHECK: (global $96 (ref null $96) (ref.null none)) + (global $96 (ref null $96) (ref.null none)) + ;; CHECK: (global $97 (ref null $97) (ref.null none)) + (global $97 (ref null $97) (ref.null none)) + ;; CHECK: (global $98 (ref null $98) (ref.null none)) + (global $98 (ref null $98) (ref.null none)) + ;; CHECK: (global $99 (ref null $99) (ref.null none)) + (global $99 (ref null $99) (ref.null none)) + ;; CHECK: (global $100 (ref null $10) (ref.null none)) + (global $100 (ref null $10) (ref.null none)) + ;; CHECK: (global $101 (ref null $11) (ref.null none)) + (global $101 (ref null $11) (ref.null none)) + ;; CHECK: (global $102 (ref null $12) (ref.null none)) + (global $102 (ref null $12) (ref.null none)) + ;; CHECK: (global $103 (ref null $13) (ref.null none)) + (global $103 (ref null $13) (ref.null none)) + ;; CHECK: (global $104 (ref null $14) (ref.null none)) + (global $104 (ref null $14) (ref.null none)) + ;; CHECK: (global $105 (ref null $15) (ref.null none)) + (global $105 (ref null $15) (ref.null none)) + ;; CHECK: (global $106 (ref null $16) (ref.null none)) + (global $106 (ref null $16) (ref.null none)) + ;; CHECK: (global $107 (ref null $17) (ref.null none)) + (global $107 (ref null $17) (ref.null none)) + ;; CHECK: (global $108 (ref null $18) (ref.null none)) + (global $108 (ref null $18) (ref.null none)) + ;; CHECK: (global $109 (ref null $19) (ref.null none)) + (global $109 (ref null $19) (ref.null none)) + ;; CHECK: (global $110 (ref null $110) (ref.null none)) + (global $110 (ref null $110) (ref.null none)) + ;; CHECK: (global $111 (ref null $111) (ref.null none)) + (global $111 (ref null $111) (ref.null none)) + ;; CHECK: (global $112 (ref null $112) (ref.null none)) + (global $112 (ref null $112) (ref.null none)) + ;; CHECK: (global $113 (ref null $113) (ref.null none)) + (global $113 (ref null $113) (ref.null none)) + ;; CHECK: (global $114 (ref null $114) (ref.null none)) + (global $114 (ref null $114) (ref.null none)) + ;; CHECK: (global $115 (ref null $115) (ref.null none)) + (global $115 (ref null $115) (ref.null none)) + ;; CHECK: (global $116 (ref null $116) (ref.null none)) + (global $116 (ref null $116) (ref.null none)) + ;; CHECK: (global $117 (ref null $117) (ref.null none)) + (global $117 (ref null $117) (ref.null none)) + ;; CHECK: (global $118 (ref null $118) (ref.null none)) + (global $118 (ref null $118) (ref.null none)) + ;; CHECK: (global $119 (ref null $119) (ref.null none)) + (global $119 (ref null $119) (ref.null none)) + ;; CHECK: (global $120 (ref null $120) (ref.null none)) + (global $120 (ref null $120) (ref.null none)) + ;; CHECK: (global $121 (ref null $121) (ref.null none)) + (global $121 (ref null $121) (ref.null none)) + ;; CHECK: (global $122 (ref null $122) (ref.null none)) + (global $122 (ref null $122) (ref.null none)) + ;; CHECK: (global $123 (ref null $123) (ref.null none)) + (global $123 (ref null $123) (ref.null none)) + ;; CHECK: (global $124 (ref null $124) (ref.null none)) + (global $124 (ref null $124) (ref.null none)) + ;; CHECK: (global $125 (ref null $125) (ref.null none)) + (global $125 (ref null $125) (ref.null none)) + ;; CHECK: (global $126 (ref null $126) (ref.null none)) + (global $126 (ref null $126) (ref.null none)) + ;; CHECK: (global $127 (ref null $127) (ref.null none)) + (global $127 (ref null $127) (ref.null none)) + ;; CHECK: (global $128 (ref null $128) (ref.null none)) + (global $128 (ref null $128) (ref.null none)) + ;; CHECK: (global $129 (ref null $129) (ref.null none)) + (global $129 (ref null $129) (ref.null none)) + ;; CHECK: (global $130 (ref null $130) (ref.null none)) + (global $130 (ref null $130) (ref.null none)) + ;; CHECK: (global $131 (ref null $131) (ref.null none)) + (global $131 (ref null $131) (ref.null none)) + ;; CHECK: (global $132 (ref null $132) (ref.null none)) + (global $132 (ref null $132) (ref.null none)) + ;; CHECK: (global $133 (ref null $133) (ref.null none)) + (global $133 (ref null $133) (ref.null none)) + ;; CHECK: (global $134 (ref null $134) (ref.null none)) + (global $134 (ref null $134) (ref.null none)) + ;; CHECK: (global $135 (ref null $135) (ref.null none)) + (global $135 (ref null $135) (ref.null none)) + ;; CHECK: (global $136 (ref null $136) (ref.null none)) + (global $136 (ref null $136) (ref.null none)) + ;; CHECK: (global $137 (ref null $137) (ref.null none)) + (global $137 (ref null $137) (ref.null none)) + ;; CHECK: (global $138 (ref null $138) (ref.null none)) + (global $138 (ref null $138) (ref.null none)) + ;; CHECK: (global $139 (ref null $139) (ref.null none)) + (global $139 (ref null $139) (ref.null none)) + ;; CHECK: (global $140 (ref null $140) (ref.null none)) + (global $140 (ref null $140) (ref.null none)) + ;; CHECK: (global $141 (ref null $141) (ref.null none)) + (global $141 (ref null $141) (ref.null none)) + ;; CHECK: (global $142 (ref null $142) (ref.null none)) + (global $142 (ref null $142) (ref.null none)) + ;; CHECK: (global $143 (ref null $143) (ref.null none)) + (global $143 (ref null $143) (ref.null none)) + ;; CHECK: (global $144 (ref null $144) (ref.null none)) + (global $144 (ref null $144) (ref.null none)) + ;; CHECK: (global $145 (ref null $145) (ref.null none)) + (global $145 (ref null $145) (ref.null none)) + ;; CHECK: (global $146 (ref null $146) (ref.null none)) + (global $146 (ref null $146) (ref.null none)) + ;; CHECK: (global $147 (ref null $147) (ref.null none)) + (global $147 (ref null $147) (ref.null none)) + ;; CHECK: (global $148 (ref null $148) (ref.null none)) + (global $148 (ref null $148) (ref.null none)) + ;; CHECK: (global $149 (ref null $149) (ref.null none)) + (global $149 (ref null $149) (ref.null none)) + ;; CHECK: (global $150 (ref null $150) (ref.null none)) + (global $150 (ref null $150) (ref.null none)) + ;; CHECK: (global $151 (ref null $151) (ref.null none)) + (global $151 (ref null $151) (ref.null none)) + ;; CHECK: (global $152 (ref null $152) (ref.null none)) + (global $152 (ref null $152) (ref.null none)) + ;; CHECK: (global $153 (ref null $153) (ref.null none)) + (global $153 (ref null $153) (ref.null none)) + ;; CHECK: (global $154 (ref null $154) (ref.null none)) + (global $154 (ref null $154) (ref.null none)) + ;; CHECK: (global $155 (ref null $155) (ref.null none)) + (global $155 (ref null $155) (ref.null none)) + ;; CHECK: (global $156 (ref null $156) (ref.null none)) + (global $156 (ref null $156) (ref.null none)) + ;; CHECK: (global $157 (ref null $157) (ref.null none)) + (global $157 (ref null $157) (ref.null none)) + ;; CHECK: (global $158 (ref null $158) (ref.null none)) + (global $158 (ref null $158) (ref.null none)) + ;; CHECK: (global $159 (ref null $159) (ref.null none)) + (global $159 (ref null $159) (ref.null none)) + ;; CHECK: (global $160 (ref null $160) (ref.null none)) + (global $160 (ref null $160) (ref.null none)) + ;; CHECK: (global $161 (ref null $161) (ref.null none)) + (global $161 (ref null $161) (ref.null none)) + ;; CHECK: (global $162 (ref null $162) (ref.null none)) + (global $162 (ref null $162) (ref.null none)) + ;; CHECK: (global $163 (ref null $163) (ref.null none)) + (global $163 (ref null $163) (ref.null none)) + ;; CHECK: (global $164 (ref null $164) (ref.null none)) + (global $164 (ref null $164) (ref.null none)) + ;; CHECK: (global $165 (ref null $165) (ref.null none)) + (global $165 (ref null $165) (ref.null none)) + ;; CHECK: (global $166 (ref null $166) (ref.null none)) + (global $166 (ref null $166) (ref.null none)) + ;; CHECK: (global $167 (ref null $167) (ref.null none)) + (global $167 (ref null $167) (ref.null none)) + ;; CHECK: (global $168 (ref null $168) (ref.null none)) + (global $168 (ref null $168) (ref.null none)) + ;; CHECK: (global $169 (ref null $169) (ref.null none)) + (global $169 (ref null $169) (ref.null none)) + ;; CHECK: (global $170 (ref null $170) (ref.null none)) + (global $170 (ref null $170) (ref.null none)) + ;; CHECK: (global $171 (ref null $171) (ref.null none)) + (global $171 (ref null $171) (ref.null none)) + ;; CHECK: (global $172 (ref null $172) (ref.null none)) + (global $172 (ref null $172) (ref.null none)) + ;; CHECK: (global $173 (ref null $173) (ref.null none)) + (global $173 (ref null $173) (ref.null none)) + ;; CHECK: (global $174 (ref null $174) (ref.null none)) + (global $174 (ref null $174) (ref.null none)) + ;; CHECK: (global $175 (ref null $175) (ref.null none)) + (global $175 (ref null $175) (ref.null none)) + ;; CHECK: (global $176 (ref null $176) (ref.null none)) + (global $176 (ref null $176) (ref.null none)) + ;; CHECK: (global $177 (ref null $177) (ref.null none)) + (global $177 (ref null $177) (ref.null none)) + ;; CHECK: (global $178 (ref null $178) (ref.null none)) + (global $178 (ref null $178) (ref.null none)) + ;; CHECK: (global $179 (ref null $179) (ref.null none)) + (global $179 (ref null $179) (ref.null none)) + ;; CHECK: (global $180 (ref null $180) (ref.null none)) + (global $180 (ref null $180) (ref.null none)) + ;; CHECK: (global $181 (ref null $181) (ref.null none)) + (global $181 (ref null $181) (ref.null none)) + ;; CHECK: (global $182 (ref null $182) (ref.null none)) + (global $182 (ref null $182) (ref.null none)) + ;; CHECK: (global $183 (ref null $183) (ref.null none)) + (global $183 (ref null $183) (ref.null none)) + ;; CHECK: (global $184 (ref null $184) (ref.null none)) + (global $184 (ref null $184) (ref.null none)) + ;; CHECK: (global $185 (ref null $185) (ref.null none)) + (global $185 (ref null $185) (ref.null none)) + ;; CHECK: (global $186 (ref null $186) (ref.null none)) + (global $186 (ref null $186) (ref.null none)) + ;; CHECK: (global $187 (ref null $187) (ref.null none)) + (global $187 (ref null $187) (ref.null none)) + ;; CHECK: (global $188 (ref null $188) (ref.null none)) + (global $188 (ref null $188) (ref.null none)) + ;; CHECK: (global $189 (ref null $189) (ref.null none)) + (global $189 (ref null $189) (ref.null none)) + ;; CHECK: (global $190 (ref null $190) (ref.null none)) + (global $190 (ref null $190) (ref.null none)) + ;; CHECK: (global $191 (ref null $191) (ref.null none)) + (global $191 (ref null $191) (ref.null none)) + ;; CHECK: (global $192 (ref null $192) (ref.null none)) + (global $192 (ref null $192) (ref.null none)) + ;; CHECK: (global $193 (ref null $193) (ref.null none)) + (global $193 (ref null $193) (ref.null none)) + ;; CHECK: (global $194 (ref null $194) (ref.null none)) + (global $194 (ref null $194) (ref.null none)) + ;; CHECK: (global $195 (ref null $195) (ref.null none)) + (global $195 (ref null $195) (ref.null none)) + ;; CHECK: (global $196 (ref null $196) (ref.null none)) + (global $196 (ref null $196) (ref.null none)) + ;; CHECK: (global $197 (ref null $197) (ref.null none)) + (global $197 (ref null $197) (ref.null none)) + ;; CHECK: (global $198 (ref null $198) (ref.null none)) + (global $198 (ref null $198) (ref.null none)) + ;; CHECK: (global $199 (ref null $199) (ref.null none)) + (global $199 (ref null $199) (ref.null none)) +) diff --git a/test/lit/passes/minimize-rec-groups.wast b/test/lit/passes/minimize-rec-groups.wast new file mode 100644 index 000000000..b1c1b1467 --- /dev/null +++ b/test/lit/passes/minimize-rec-groups.wast @@ -0,0 +1,486 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: foreach %s %t wasm-opt -all --minimize-rec-groups -S -o - | filecheck %s + +;; A module with no heap types at all should be ok. +(module + ;; CHECK: (global $g i32 (i32.const 0)) + (global $g i32 (i32.const 0)) +) + +;; A module with a single heap type should be ok. +(module + ;; CHECK: (type $t (struct)) + (type $t (struct)) + ;; CHECK: (global $g (ref null $t) (ref.null none)) + (global $g (ref null $t) (ref.null none)) +) + +;; Split a rec group containing independent types +(module + (rec + ;; CHECK: (type $a (struct (field i32))) + (type $a (struct (field i32))) + ;; CHECK: (type $b (struct (field i64))) + (type $b (struct (field i64))) + ;; CHECK: (type $c (struct (field f32))) + (type $c (struct (field f32))) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) +) + +;; Split a rec group containing types that depend on each other but belong to +;; different SCCs. +(module + (rec + ;; CHECK: (type $a (struct)) + (type $a (struct)) + ;; CHECK: (type $b (struct (field (ref $a)))) + (type $b (struct (field (ref $a)))) + ;; CHECK: (type $c (struct (field (ref $b)))) + (type $c (struct (field (ref $b)))) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) +) + +;; Reverse the order of the previous case. The output should still be in a valid +;; order. +(module + (rec + ;; CHECK: (type $a (struct)) + + ;; CHECK: (type $b (struct (field (ref $a)))) + + ;; CHECK: (type $c (struct (field (ref $b)))) + (type $c (struct (field (ref $b)))) + (type $b (struct (field (ref $a)))) + (type $a (struct)) + ) + + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) +) + +;; Now all the types are in the same SCC. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $c (struct (field (ref $a)))) + + ;; CHECK: (type $b (struct (field (ref $c)))) + + ;; CHECK: (type $a (struct (field (ref $b)))) + (type $a (struct (field (ref $b)))) + (type $b (struct (field (ref $c)))) + (type $c (struct (field (ref $a)))) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) +) + +;; Only two of the types are in the same SCC. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $b (struct (field (ref $a)))) + + ;; CHECK: (type $a (struct (field (ref $b)))) + (type $a (struct (field (ref $b)))) + (type $b (struct (field (ref $a)))) + ;; CHECK: (type $c (struct (field (ref $a)))) + (type $c (struct (field (ref $a)))) + ) + + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) +) + +;; Same, but change which two are in the SCC. The output order should still be +;; valid. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $c (struct (field (ref $b)))) + + ;; CHECK: (type $b (struct (field (ref $c)))) + + ;; CHECK: (type $a (struct (field (ref $b)))) + (type $a (struct (field (ref $b)))) + (type $b (struct (field (ref $c)))) + (type $c (struct (field (ref $b)))) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) +) + +;; Two types that are in conflicting SCCs should be disambiguated. In this case +;; there are no different permutations, so we use a brand. +(module + (rec + ;; CHECK: (type $a (func)) + (type $a (func)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (struct)) + + ;; CHECK: (type $b (func)) + (type $b (func)) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null nofunc)) + (global $a (ref null $a) (ref.null nofunc)) + ;; CHECK: (global $b (ref null $b) (ref.null nofunc)) + (global $b (ref null $b) (ref.null nofunc)) +) + +;; Same as above, but now the types match the initial brand, so we have to skip +;; to the next one. +(module + (rec + ;; CHECK: (type $a (struct)) + (type $a (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (array (mut i8))) + + ;; CHECK: (type $b (struct)) + (type $b (struct)) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) +) + +;; Now we have groups that match both the initial brand and the next one, so +;; adding the brand will cause a conflict. We will have to go to the next brand. +(module + (rec + ;; CHECK: (type $a1 (struct)) + (type $a1 (struct)) + ;; CHECK: (type $b1 (array (mut i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (array (mut i8))) + + ;; CHECK: (type $a2 (struct)) + (type $a2 (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a3 (struct)) + (type $a3 (struct)) + (type $b1 (array (mut i8))) + ;; CHECK: (type $5 (array (mut i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $6 (array i8)) + + ;; CHECK: (type $b2 (array (mut i8))) + (type $b2 (array (mut i8))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) + ;; CHECK: (global $a3 (ref null $a3) (ref.null none)) + (global $a3 (ref null $a3) (ref.null none)) + ;; CHECK: (global $b1 (ref null $b1) (ref.null none)) + (global $b1 (ref null $b1) (ref.null none)) + ;; CHECK: (global $b2 (ref null $b2) (ref.null none)) + (global $b2 (ref null $b2) (ref.null none)) +) + +;; Now the types have more fields, including one referring to a previous SCC. +(module + (rec + ;; CHECK: (type $other (struct (field i32))) + (type $other (struct (field i32))) + ;; CHECK: (type $a (struct (field anyref) (field i32) (field (ref $other)))) + (type $a (struct (field anyref i32 (ref $other)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (struct)) + + ;; CHECK: (type $b (struct (field anyref) (field i32) (field (ref $other)))) + (type $b (struct (field anyref i32 (ref $other)))) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) +) + +;; Now there is a third type and we can disambiguate it by using a different +;; permutation with the same brand. +(module + (rec + ;; CHECK: (type $a (struct)) + (type $a (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (array (mut i8))) + + ;; CHECK: (type $b (struct)) + (type $b (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $c (struct)) + (type $c (struct)) + ) + + ;; CHECK: (type $4 (array (mut i8))) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) +) + +;; Adding a fourth type requires using yet another brand. +(module + (rec + ;; CHECK: (type $a (struct)) + (type $a (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $1 (array (mut i8))) + + ;; CHECK: (type $b (struct)) + (type $b (struct)) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $c (struct)) + (type $c (struct)) + ;; CHECK: (type $4 (array (mut i8))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $5 (array i8)) + + ;; CHECK: (type $d (struct)) + (type $d (struct)) + ) + + ;; CHECK: (global $a (ref null $a) (ref.null none)) + (global $a (ref null $a) (ref.null none)) + ;; CHECK: (global $b (ref null $b) (ref.null none)) + (global $b (ref null $b) (ref.null none)) + ;; CHECK: (global $c (ref null $c) (ref.null none)) + (global $c (ref null $c) (ref.null none)) + ;; CHECK: (global $d (ref null $d) (ref.null none)) + (global $d (ref null $d) (ref.null none)) +) + +;; After $a1 and $a2 are dismabiguated with a brand, $b1 and $b2 require no +;; further disambiguation. +(module + (rec + ;; CHECK: (type $a1 (struct)) + (type $a1 (struct)) + ;; CHECK: (type $b1 (struct (field (ref $a1)))) + + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (array (mut i8))) + + ;; CHECK: (type $a2 (struct)) + (type $a2 (struct)) + (type $b1 (struct (field (ref $a1)))) + ;; CHECK: (type $b2 (struct (field (ref $a2)))) + (type $b2 (struct (field (ref $a2)))) + ) + + ;; CHECK: (global $b1 (ref null $b1) (ref.null none)) + (global $b1 (ref null $b1) (ref.null none)) + ;; CHECK: (global $b2 (ref null $b2) (ref.null none)) + (global $b2 (ref null $b2) (ref.null none)) +) + +;; Now we can disambiguate by permuting without a brand. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $b1 (struct (field (ref $a1)))) + + ;; CHECK: (type $a1 (struct (field (ref $b1)) (field i32))) + (type $a1 (struct (field (ref $b1) i32))) + (type $b1 (struct (field (ref $a1)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a2 (struct (field (ref $b2)) (field i32))) + (type $a2 (struct (field (ref $b2) i32))) + ;; CHECK: (type $b2 (struct (field (ref $a2)))) + (type $b2 (struct (field (ref $a2)))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) +) + +;; But when we run out of permutations, we need a brand again. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $b1 (struct (field (ref $a1)))) + + ;; CHECK: (type $a1 (struct (field (ref $b1)) (field i32))) + (type $a1 (struct (field (ref $b1) i32))) + (type $b1 (struct (field (ref $a1)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a2 (struct (field (ref $b2)) (field i32))) + (type $a2 (struct (field (ref $b2) i32))) + ;; CHECK: (type $b2 (struct (field (ref $a2)))) + (type $b2 (struct (field (ref $a2)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $4 (struct)) + + ;; CHECK: (type $b3 (struct (field (ref $a3)))) + + ;; CHECK: (type $a3 (struct (field (ref $b3)) (field i32))) + (type $a3 (struct (field (ref $b3) i32))) + (type $b3 (struct (field (ref $a3)))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) + ;; CHECK: (global $a3 (ref null $a3) (ref.null none)) + (global $a3 (ref null $a3) (ref.null none)) +) + +;; Same as above, except the middle global now refers to $b2 instead of $a2, +;; changing the initial order of types in the middle SCC. We arrive at the same +;; result by a different path. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $b1 (struct (field (ref $a1)))) + + ;; CHECK: (type $a1 (struct (field (ref $b1)) (field i32))) + (type $a1 (struct (field (ref $b1) i32))) + (type $b1 (struct (field (ref $a1)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a2 (struct (field (ref $b2)) (field i32))) + (type $a2 (struct (field (ref $b2) i32))) + ;; CHECK: (type $b2 (struct (field (ref $a2)))) + (type $b2 (struct (field (ref $a2)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $4 (struct)) + + ;; CHECK: (type $b3 (struct (field (ref $a3)))) + + ;; CHECK: (type $a3 (struct (field (ref $b3)) (field i32))) + (type $a3 (struct (field (ref $b3) i32))) + (type $b3 (struct (field (ref $a3)))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $b2 (ref null $b2) (ref.null none)) + (global $b2 (ref null $b2) (ref.null none)) + ;; CHECK: (global $a3 (ref null $a3) (ref.null none)) + (global $a3 (ref null $a3) (ref.null none)) +) + +;; Now we can't differentiate by permutation because of automorphisms. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $b1 (struct (field (ref $a1)))) + + ;; CHECK: (type $a1 (struct (field (ref $b1)))) + (type $a1 (struct (field (ref $b1)))) + (type $b1 (struct (field (ref $a1)))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (struct)) + + ;; CHECK: (type $b2 (struct (field (ref $a2)))) + + ;; CHECK: (type $a2 (struct (field (ref $b2)))) + (type $a2 (struct (field (ref $b2)))) + (type $b2 (struct (field (ref $a2)))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) +) + +;; Now we can't differentiate by permutation because the subtyping constraint +;; admits only one ordering. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a1 (sub (struct (field (ref $b1))))) + (type $a1 (sub (struct (field (ref $b1))))) + ;; CHECK: (type $b1 (sub $a1 (struct (field (ref $b1))))) + (type $b1 (sub $a1 (struct (field (ref $b1))))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $2 (struct)) + + ;; CHECK: (type $a2 (sub (struct (field (ref $b2))))) + (type $a2 (sub (struct (field (ref $b2))))) + ;; CHECK: (type $b2 (sub $a2 (struct (field (ref $b2))))) + (type $b2 (sub $a2 (struct (field (ref $b2))))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) +) + + +;; Now there are only two possible orderings admitted by the subtyping +;; constraint. +(module + (rec + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a1 (sub (struct (field (ref $b1))))) + (type $a1 (sub (struct (field (ref $b1))))) + ;; CHECK: (type $c1 (sub $a1 (struct (field (ref $b1))))) + + ;; CHECK: (type $b1 (sub $a1 (struct (field (ref $b1)) (field (ref $c1))))) + (type $b1 (sub $a1 (struct (field (ref $b1)) (ref $c1)))) + (type $c1 (sub $a1 (struct (field (ref $b1))))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $a2 (sub (struct (field (ref $b2))))) + (type $a2 (sub (struct (field (ref $b2))))) + ;; CHECK: (type $b2 (sub $a2 (struct (field (ref $b2)) (field (ref $c2))))) + (type $b2 (sub $a2 (struct (field (ref $b2)) (ref $c2)))) + ;; CHECK: (type $c2 (sub $a2 (struct (field (ref $b2))))) + (type $c2 (sub $a2 (struct (field (ref $b2))))) + ;; CHECK: (rec + ;; CHECK-NEXT: (type $6 (struct)) + + ;; CHECK: (type $a3 (sub (struct (field (ref $b3))))) + (type $a3 (sub (struct (field (ref $b3))))) + ;; CHECK: (type $c3 (sub $a3 (struct (field (ref $b3))))) + + ;; CHECK: (type $b3 (sub $a3 (struct (field (ref $b3)) (field (ref $c3))))) + (type $b3 (sub $a3 (struct (field (ref $b3)) (ref $c3)))) + (type $c3 (sub $a3 (struct (field (ref $b3))))) + ) + + ;; CHECK: (global $a1 (ref null $a1) (ref.null none)) + (global $a1 (ref null $a1) (ref.null none)) + ;; CHECK: (global $a2 (ref null $a2) (ref.null none)) + (global $a2 (ref null $a2) (ref.null none)) + ;; CHECK: (global $a3 (ref null $a3) (ref.null none)) + (global $a3 (ref null $a3) (ref.null none)) +) |