Skip to content

Commit a84b026

Browse files
authored
Do not rewrite supertypes in AbstractTypeRefining (#7720)
Keeping descriptor chains valid while rewriting subtyping is complicated. Make it simpler to optimize descriptor and described types in a future PR by not rewriting supertypes at all in AbstractTypeRefining. To avoid losing optimization power in the default optimization pipelines, run Unsubtyping after AbstractTypeRefining. This makes -O3 slightly faster when optimizing Sheets calcengine (possibly because having fewer subtype relationships leads to less work in later optimizations) and improves code size by 0.1%. The improvements increase when running -O3 -O3, with a 1.7% code size improvement relative to the same pipeline before this change.
1 parent b440e68 commit a84b026

File tree

3 files changed

+46
-41
lines changed

3 files changed

+46
-41
lines changed

src/passes/AbstractTypeRefining.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -275,29 +275,26 @@ 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 keeping descriptor chains valid is
288+
// nontrivial. Instead, avoid changing subtype relationships entirely: leave
289+
// that for Unsubtyping.
286290
class AbstractTypeRefiningTypeMapper : public TypeMapper {
287291
public:
288292
AbstractTypeRefiningTypeMapper(Module& wasm, const TypeUpdates& mapping)
289293
: TypeMapper(wasm, mapping) {}
290294

291295
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;
296+
// We do not want to update subtype relationships.
297+
return oldType.getDeclaredSuperType();
301298
}
302299
};
303300

src/passes/pass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ void PassRunner::addDefaultGlobalOptimizationPrePasses() {
761761
addIfNoDWARFIssues("cfp");
762762
addIfNoDWARFIssues("gsi");
763763
addIfNoDWARFIssues("abstract-type-refining");
764+
addIfNoDWARFIssues("unsubtyping");
764765
}
765766
}
766767
// TODO: generate-global-effects here, right before function passes, then

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)