Skip to content

Commit ff51aee

Browse files
committed
[DRAFT] Do not rewrite supertypes in AbstractTypeRefining
Keeping descriptor chains valid while rewriting subtyping is complicated. Make it simpler to optimize descriptor and described types by not rewriting supertypes at all in AbstractTypeRefining. Landing this is blocked on making Unsubtyping more efficient so we can use it by default as a follow-up to AbstractTypeRefining to avoid regressions.
1 parent a5665c8 commit ff51aee

File tree

2 files changed

+44
-41
lines changed

2 files changed

+44
-41
lines changed

src/passes/AbstractTypeRefining.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -275,29 +275,25 @@ struct AbstractTypeRefining : public Pass {
275275
return;
276276
}
277277

278-
// A TypeMapper that handles the patterns we have in our mapping, where we
279-
// end up mapping a type to a *subtype*. We need to properly create
280-
// supertypes while doing this rewriting. For example, say we have this:
278+
// Rewriting types can usually rewrite subtype relationships. For example,
279+
// if we have this:
281280
//
282-
// A :> B :> C
281+
// C <: B <: A
283282
//
284-
// Say we see B is never created, so we want to map B to its subtype C. C's
285-
// supertype must now be A.
283+
// And we see that B is never created, we would naively map B to its subtype
284+
// C. But if we rewrote C's supertype, C would declare itself to be its own
285+
// supertype, which is not allowed. We could fix this by walking up the
286+
// supertype chain to find a supertype that is not being rewritten, but
287+
// changing subtype relationships and keep descriptor chains valid is
288+
// nontrivial. Instead, avoid changing subtype relationships entirely.
286289
class AbstractTypeRefiningTypeMapper : public TypeMapper {
287290
public:
288291
AbstractTypeRefiningTypeMapper(Module& wasm, const TypeUpdates& mapping)
289292
: TypeMapper(wasm, mapping) {}
290293

291294
std::optional<HeapType> getDeclaredSuperType(HeapType oldType) override {
292-
auto super = oldType.getDeclaredSuperType();
293-
294-
// Go up the chain of supertypes, skipping things we are mapping away,
295-
// as those things will not appear in the output. This skips B in the
296-
// example above.
297-
while (super && mapping.count(*super)) {
298-
super = super->getDeclaredSuperType();
299-
}
300-
return super;
295+
// We do not want to update subtype relationships.
296+
return oldType.getDeclaredSuperType();
301297
}
302298
};
303299

test/lit/passes/abstract-type-refining.wast

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,31 @@
1313
;; actually refer to a subtype of them (that has a struct.new). As a result, in
1414
;; TNH mode $A and $D will also not be emitted in the output anymore.
1515
(module
16+
;; YESTNH: (rec
17+
;; YESTNH-NEXT: (type $A (sub (struct)))
1618
;; NO_TNH: (rec
1719
;; NO_TNH-NEXT: (type $A (sub (struct)))
1820
(type $A (sub (struct)))
1921

20-
;; YESTNH: (rec
21-
;; YESTNH-NEXT: (type $B (sub (struct)))
22+
;; YESTNH: (type $B (sub $A (struct)))
2223
;; NO_TNH: (type $B (sub $A (struct)))
2324
(type $B (sub $A (struct)))
2425

2526
;; YESTNH: (type $C (sub $B (struct)))
2627
;; NO_TNH: (type $C (sub $B (struct)))
2728
(type $C (sub $B (struct)))
2829

30+
;; YESTNH: (type $D (sub $C (struct)))
2931
;; NO_TNH: (type $D (sub $C (struct)))
3032
(type $D (sub $C (struct)))
3133

32-
;; YESTNH: (type $E (sub $C (struct)))
34+
;; YESTNH: (type $E (sub $D (struct)))
3335
;; NO_TNH: (type $E (sub $D (struct)))
3436
(type $E (sub $D (struct)))
3537

36-
;; YESTNH: (type $3 (func (param anyref)))
38+
;; YESTNH: (type $5 (func (param anyref)))
3739

38-
;; YESTNH: (type $4 (func))
40+
;; YESTNH: (type $6 (func))
3941

4042
;; YESTNH: (global $global anyref (struct.new_default $B))
4143
;; NO_TNH: (type $5 (func (param anyref)))
@@ -45,7 +47,7 @@
4547
;; NO_TNH: (global $global anyref (struct.new_default $B))
4648
(global $global anyref (struct.new $B))
4749

48-
;; YESTNH: (func $new (type $3) (param $x anyref)
50+
;; YESTNH: (func $new (type $5) (param $x anyref)
4951
;; YESTNH-NEXT: (drop
5052
;; YESTNH-NEXT: (struct.new_default $C)
5153
;; YESTNH-NEXT: )
@@ -70,7 +72,7 @@
7072
)
7173
)
7274

73-
;; YESTNH: (func $ref.cast (type $3) (param $x anyref)
75+
;; YESTNH: (func $ref.cast (type $5) (param $x anyref)
7476
;; YESTNH-NEXT: (drop
7577
;; YESTNH-NEXT: (ref.cast (ref $B)
7678
;; YESTNH-NEXT: (local.get $x)
@@ -154,7 +156,7 @@
154156
)
155157
)
156158

157-
;; YESTNH: (func $ref.test (type $3) (param $x anyref)
159+
;; YESTNH: (func $ref.test (type $5) (param $x anyref)
158160
;; YESTNH-NEXT: (drop
159161
;; YESTNH-NEXT: (ref.test (ref $B)
160162
;; YESTNH-NEXT: (local.get $x)
@@ -176,7 +178,7 @@
176178
)
177179
)
178180

179-
;; YESTNH: (func $br_on (type $3) (param $x anyref)
181+
;; YESTNH: (func $br_on (type $5) (param $x anyref)
180182
;; YESTNH-NEXT: (drop
181183
;; YESTNH-NEXT: (block $block (result (ref $B))
182184
;; YESTNH-NEXT: (drop
@@ -213,7 +215,7 @@
213215
)
214216
)
215217

216-
;; YESTNH: (func $basic (type $3) (param $x anyref)
218+
;; YESTNH: (func $basic (type $5) (param $x anyref)
217219
;; YESTNH-NEXT: (drop
218220
;; YESTNH-NEXT: (ref.cast (ref struct)
219221
;; YESTNH-NEXT: (local.get $x)
@@ -236,7 +238,7 @@
236238
)
237239
)
238240

239-
;; YESTNH: (func $locals (type $4)
241+
;; YESTNH: (func $locals (type $6)
240242
;; YESTNH-NEXT: (local $A (ref $B))
241243
;; YESTNH-NEXT: (local $B (ref $B))
242244
;; YESTNH-NEXT: (local $C (ref $C))
@@ -359,21 +361,22 @@
359361
;; $B1.
360362
(module
361363
(rec
364+
;; YESTNH: (rec
365+
;; YESTNH-NEXT: (type $A (sub (struct)))
362366
;; NO_TNH: (rec
363367
;; NO_TNH-NEXT: (type $A (sub (struct)))
364368
(type $A (sub (struct)))
365369

366370
(type $B (sub $A (struct)))
367371

368-
;; YESTNH: (rec
369-
;; YESTNH-NEXT: (type $B1 (sub (struct)))
372+
;; YESTNH: (type $B1 (sub $A (struct)))
370373
;; NO_TNH: (type $B1 (sub $A (struct)))
371374
(type $B1 (sub $A (struct))) ;; this is a new type
372375
)
373376

374-
;; YESTNH: (type $1 (func (param anyref)))
377+
;; YESTNH: (type $2 (func (param anyref)))
375378

376-
;; YESTNH: (func $new (type $1) (param $x anyref)
379+
;; YESTNH: (func $new (type $2) (param $x anyref)
377380
;; YESTNH-NEXT: (drop
378381
;; YESTNH-NEXT: (struct.new_default $B1)
379382
;; YESTNH-NEXT: )
@@ -391,7 +394,7 @@
391394
)
392395
)
393396

394-
;; YESTNH: (func $ref.cast (type $1) (param $x anyref)
397+
;; YESTNH: (func $ref.cast (type $2) (param $x anyref)
395398
;; YESTNH-NEXT: (drop
396399
;; YESTNH-NEXT: (ref.cast (ref $B1)
397400
;; YESTNH-NEXT: (local.get $x)
@@ -446,21 +449,23 @@
446449

447450
;; A chain, $A :> $B :> $C, where we can optimize $A all the way to $C.
448451
(module
452+
;; YESTNH: (rec
453+
;; YESTNH-NEXT: (type $A (sub (struct)))
449454
;; NO_TNH: (rec
450455
;; NO_TNH-NEXT: (type $A (sub (struct)))
451456
(type $A (sub (struct)))
452457

458+
;; YESTNH: (type $B (sub $A (struct)))
453459
;; NO_TNH: (type $B (sub $A (struct)))
454460
(type $B (sub $A (struct)))
455461

456-
;; YESTNH: (rec
457-
;; YESTNH-NEXT: (type $C (sub (struct)))
462+
;; YESTNH: (type $C (sub $B (struct)))
458463
;; NO_TNH: (type $C (sub $B (struct)))
459464
(type $C (sub $B (struct)))
460465

461-
;; YESTNH: (type $1 (func (param anyref)))
466+
;; YESTNH: (type $3 (func (param anyref)))
462467

463-
;; YESTNH: (func $new (type $1) (param $x anyref)
468+
;; YESTNH: (func $new (type $3) (param $x anyref)
464469
;; YESTNH-NEXT: (drop
465470
;; YESTNH-NEXT: (struct.new_default $C)
466471
;; YESTNH-NEXT: )
@@ -478,7 +483,7 @@
478483
)
479484
)
480485

481-
;; YESTNH: (func $ref.cast (type $1) (param $x anyref)
486+
;; YESTNH: (func $ref.cast (type $3) (param $x anyref)
482487
;; YESTNH-NEXT: (drop
483488
;; YESTNH-NEXT: (ref.cast (ref $C)
484489
;; YESTNH-NEXT: (local.get $x)
@@ -817,30 +822,32 @@
817822
;; As above, but now $C1 is created.
818823
(module
819824
(rec
825+
;; YESTNH: (rec
826+
;; YESTNH-NEXT: (type $A (sub (struct)))
820827
;; NO_TNH: (rec
821828
;; NO_TNH-NEXT: (type $A (sub (struct)))
822829
(type $A (sub (struct)))
823830

831+
;; YESTNH: (type $B (sub $A (struct)))
824832
;; NO_TNH: (type $B (sub $A (struct)))
825833
(type $B (sub $A (struct)))
826834

827-
;; YESTNH: (rec
828-
;; YESTNH-NEXT: (type $C1 (sub (struct)))
835+
;; YESTNH: (type $C1 (sub $B (struct)))
829836
;; NO_TNH: (type $C1 (sub $B (struct)))
830837
(type $C1 (sub $B (struct)))
831838

832839
(type $C2 (sub $B (struct)))
833840
)
834841

835-
;; YESTNH: (type $1 (func (param anyref)))
842+
;; YESTNH: (type $3 (func (param anyref)))
836843

837844
;; YESTNH: (global $global anyref (struct.new_default $C1))
838845
;; NO_TNH: (type $3 (func (param anyref)))
839846

840847
;; NO_TNH: (global $global anyref (struct.new_default $C1))
841848
(global $global anyref (struct.new $C1))
842849

843-
;; YESTNH: (func $ref.cast (type $1) (param $x anyref)
850+
;; YESTNH: (func $ref.cast (type $3) (param $x anyref)
844851
;; YESTNH-NEXT: (drop
845852
;; YESTNH-NEXT: (ref.cast (ref $C1)
846853
;; YESTNH-NEXT: (local.get $x)
@@ -909,7 +916,7 @@
909916
)
910917
)
911918

912-
;; YESTNH: (func $ref.cast.null (type $1) (param $x anyref)
919+
;; YESTNH: (func $ref.cast.null (type $3) (param $x anyref)
913920
;; YESTNH-NEXT: (drop
914921
;; YESTNH-NEXT: (ref.cast (ref null $C1)
915922
;; YESTNH-NEXT: (local.get $x)

0 commit comments

Comments
 (0)