summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-08-16 22:14:06 -0400
committerGitHub <noreply@github.com>2024-08-17 02:14:06 +0000
commite058bfbdf31c7b59df8ab62a9ebaedac45521c12 (patch)
treeffdb01a6e5f76057a6f654c2df29f0c6e551d276 /test
parent95a4d5de6f65b35a64caf014c2f7febb8a799542 (diff)
downloadbinaryen-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.test3
-rw-r--r--test/lit/help/wasm-opt.test3
-rw-r--r--test/lit/help/wasm2js.test3
-rw-r--r--test/lit/passes/minimize-rec-groups-brands.wast1378
-rw-r--r--test/lit/passes/minimize-rec-groups.wast486
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))
+)