Skip to content

Commit d2469f2

Browse files
authored
[Custom Descriptors] OptimizeInstructions: Handle effects in ref.cast_desc when removing ref.as_non_null (#8133)
1 parent 4f7136b commit d2469f2

File tree

2 files changed

+107
-17
lines changed

2 files changed

+107
-17
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,6 +2551,17 @@ struct OptimizeInstructions
25512551
// (ref.cast (ref T) ..)
25522552
//
25532553
if (auto* as = curr->ref->dynCast<RefAs>(); as && as->op == RefAsNonNull) {
2554+
if (curr->desc) {
2555+
// There is another child here, whose effects we must consider (the same
2556+
// ordering situation as in skipNonNullCast: we want to move a trap on
2557+
// null past later children).
2558+
auto& options = getPassRunner()->options;
2559+
EffectAnalyzer descEffects(options, *getModule(), curr->desc);
2560+
ShallowEffectAnalyzer movingEffects(options, *getModule(), curr->ref);
2561+
if (descEffects.invalidates(movingEffects)) {
2562+
return;
2563+
}
2564+
}
25542565
curr->ref = as->value;
25552566
curr->type = curr->type.with(NonNullable);
25562567
}

test/lit/passes/optimize-instructions-desc.wast

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
(type $struct-i32.desc (describes $struct-i32) (struct))
3838
)
3939

40-
;; CHECK: (import "" "" (func $effect (type $6)))
41-
;; NTRAP: (import "" "" (func $effect (type $6)))
40+
;; CHECK: (import "" "" (func $effect (type $4)))
41+
;; NTRAP: (import "" "" (func $effect (type $4)))
4242
(import "" "" (func $effect))
4343

4444
;; CHECK: (func $trap-null-desc (type $10) (result (ref (exact $struct)))
@@ -128,12 +128,12 @@
128128
)
129129
)
130130

131-
;; CHECK: (func $cast-desc-null-desc (type $6)
131+
;; CHECK: (func $cast-desc-null-desc (type $4)
132132
;; CHECK-NEXT: (drop
133133
;; CHECK-NEXT: (unreachable)
134134
;; CHECK-NEXT: )
135135
;; CHECK-NEXT: )
136-
;; NTRAP: (func $cast-desc-null-desc (type $6)
136+
;; NTRAP: (func $cast-desc-null-desc (type $4)
137137
;; NTRAP-NEXT: (drop
138138
;; NTRAP-NEXT: (unreachable)
139139
;; NTRAP-NEXT: )
@@ -375,7 +375,7 @@
375375
)
376376
)
377377

378-
;; CHECK: (func $cast-desc-wrong-desc (type $6)
378+
;; CHECK: (func $cast-desc-wrong-desc (type $4)
379379
;; CHECK-NEXT: (drop
380380
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
381381
;; CHECK-NEXT: (struct.new_default_desc $struct
@@ -385,7 +385,7 @@
385385
;; CHECK-NEXT: )
386386
;; CHECK-NEXT: )
387387
;; CHECK-NEXT: )
388-
;; NTRAP: (func $cast-desc-wrong-desc (type $6)
388+
;; NTRAP: (func $cast-desc-wrong-desc (type $4)
389389
;; NTRAP-NEXT: (drop
390390
;; NTRAP-NEXT: (block (result (ref (exact $struct)))
391391
;; NTRAP-NEXT: (struct.new_default_desc $struct
@@ -409,7 +409,7 @@
409409
)
410410
)
411411

412-
;; CHECK: (func $cast-desc-wrong-desc-effects (type $6)
412+
;; CHECK: (func $cast-desc-wrong-desc-effects (type $4)
413413
;; CHECK-NEXT: (drop
414414
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
415415
;; CHECK-NEXT: (block (result (ref (exact $struct)))
@@ -425,7 +425,7 @@
425425
;; CHECK-NEXT: )
426426
;; CHECK-NEXT: )
427427
;; CHECK-NEXT: )
428-
;; NTRAP: (func $cast-desc-wrong-desc-effects (type $6)
428+
;; NTRAP: (func $cast-desc-wrong-desc-effects (type $4)
429429
;; NTRAP-NEXT: (local $0 (ref (exact $struct)))
430430
;; NTRAP-NEXT: (local $1 (ref (exact $desc)))
431431
;; NTRAP-NEXT: (drop
@@ -497,9 +497,11 @@
497497
;; CHECK: (func $cast-desc-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
498498
;; CHECK-NEXT: (drop
499499
;; CHECK-NEXT: (ref.cast_desc (ref $sub)
500-
;; CHECK-NEXT: (block (result anyref)
501-
;; CHECK-NEXT: (call $effect)
502-
;; CHECK-NEXT: (local.get $ref)
500+
;; CHECK-NEXT: (ref.as_non_null
501+
;; CHECK-NEXT: (block (result anyref)
502+
;; CHECK-NEXT: (call $effect)
503+
;; CHECK-NEXT: (local.get $ref)
504+
;; CHECK-NEXT: )
503505
;; CHECK-NEXT: )
504506
;; CHECK-NEXT: (block (result (ref $sub.desc))
505507
;; CHECK-NEXT: (call $effect)
@@ -511,9 +513,11 @@
511513
;; NTRAP: (func $cast-desc-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
512514
;; NTRAP-NEXT: (drop
513515
;; NTRAP-NEXT: (ref.cast_desc (ref $sub)
514-
;; NTRAP-NEXT: (block (result anyref)
515-
;; NTRAP-NEXT: (call $effect)
516-
;; NTRAP-NEXT: (local.get $ref)
516+
;; NTRAP-NEXT: (ref.as_non_null
517+
;; NTRAP-NEXT: (block (result anyref)
518+
;; NTRAP-NEXT: (call $effect)
519+
;; NTRAP-NEXT: (local.get $ref)
520+
;; NTRAP-NEXT: )
517521
;; NTRAP-NEXT: )
518522
;; NTRAP-NEXT: (block (result (ref $sub.desc))
519523
;; NTRAP-NEXT: (call $effect)
@@ -524,7 +528,8 @@
524528
;; NTRAP-NEXT: )
525529
(func $cast-desc-weaker-nondesc-child-effects (param $ref anyref) (param $desc (ref $sub.desc))
526530
(drop
527-
;; Same, but with effects.
531+
;; Same, but with effects. Due to ordering, we cannot remove the inner
532+
;; cast (which turns into ref.as_non_null).
528533
(ref.cast_desc (ref $sub)
529534
(ref.cast (ref any)
530535
(block (result anyref)
@@ -1073,7 +1078,7 @@
10731078
)
10741079
)
10751080

1076-
;; CHECK: (func $cast-desc-unreachable-desc (type $6)
1081+
;; CHECK: (func $cast-desc-unreachable-desc (type $4)
10771082
;; CHECK-NEXT: (drop
10781083
;; CHECK-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
10791084
;; CHECK-NEXT: (drop
@@ -1086,7 +1091,7 @@
10861091
;; CHECK-NEXT: )
10871092
;; CHECK-NEXT: )
10881093
;; CHECK-NEXT: )
1089-
;; NTRAP: (func $cast-desc-unreachable-desc (type $6)
1094+
;; NTRAP: (func $cast-desc-unreachable-desc (type $4)
10901095
;; NTRAP-NEXT: (drop
10911096
;; NTRAP-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
10921097
;; NTRAP-NEXT: (drop
@@ -1380,4 +1385,78 @@
13801385
)
13811386
)
13821387
)
1388+
1389+
;; CHECK: (func $ref.cast_desc-ref.as_non_null (type $4)
1390+
;; CHECK-NEXT: (local $null (ref null $struct))
1391+
;; CHECK-NEXT: (drop
1392+
;; CHECK-NEXT: (ref.cast_desc (ref $struct)
1393+
;; CHECK-NEXT: (ref.as_non_null
1394+
;; CHECK-NEXT: (local.get $null)
1395+
;; CHECK-NEXT: )
1396+
;; CHECK-NEXT: (block (result (ref null $desc))
1397+
;; CHECK-NEXT: (return)
1398+
;; CHECK-NEXT: )
1399+
;; CHECK-NEXT: )
1400+
;; CHECK-NEXT: )
1401+
;; CHECK-NEXT: (drop
1402+
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
1403+
;; CHECK-NEXT: (local.get $null)
1404+
;; CHECK-NEXT: (struct.new_default $desc)
1405+
;; CHECK-NEXT: )
1406+
;; CHECK-NEXT: )
1407+
;; CHECK-NEXT: )
1408+
;; NTRAP: (func $ref.cast_desc-ref.as_non_null (type $4)
1409+
;; NTRAP-NEXT: (local $null (ref null $struct))
1410+
;; NTRAP-NEXT: (local $1 (ref $struct))
1411+
;; NTRAP-NEXT: (local $2 (ref null $desc))
1412+
;; NTRAP-NEXT: (drop
1413+
;; NTRAP-NEXT: (block (result (ref $struct))
1414+
;; NTRAP-NEXT: (local.set $1
1415+
;; NTRAP-NEXT: (ref.as_non_null
1416+
;; NTRAP-NEXT: (local.get $null)
1417+
;; NTRAP-NEXT: )
1418+
;; NTRAP-NEXT: )
1419+
;; NTRAP-NEXT: (local.set $2
1420+
;; NTRAP-NEXT: (block (result (ref null $desc))
1421+
;; NTRAP-NEXT: (return)
1422+
;; NTRAP-NEXT: )
1423+
;; NTRAP-NEXT: )
1424+
;; NTRAP-NEXT: (local.get $1)
1425+
;; NTRAP-NEXT: )
1426+
;; NTRAP-NEXT: )
1427+
;; NTRAP-NEXT: (drop
1428+
;; NTRAP-NEXT: (ref.cast_desc (ref (exact $struct))
1429+
;; NTRAP-NEXT: (local.get $null)
1430+
;; NTRAP-NEXT: (struct.new_default $desc)
1431+
;; NTRAP-NEXT: )
1432+
;; NTRAP-NEXT: )
1433+
;; NTRAP-NEXT: )
1434+
(func $ref.cast_desc-ref.as_non_null
1435+
(local $null (ref null $struct))
1436+
;; We read a null local and cast it to non-null, trapping. The ref.cast_desc
1437+
;; would trap on null anyhow, so it seems we can remove the ref.as_non_null,
1438+
;; but doing so would allow us to reach the block, which returns *before* the
1439+
;; ref.cast_desc would trap.
1440+
(drop
1441+
(ref.cast_desc (ref $struct)
1442+
(ref.as_non_null
1443+
(local.get $null)
1444+
)
1445+
;; Hide the return in a block, otherwise we'd skip unreachable code.
1446+
(block (result (ref null $desc))
1447+
(return)
1448+
)
1449+
)
1450+
)
1451+
;; As above, but without dangerous effects: we can remove the
1452+
;; ref.as_non_null.
1453+
(drop
1454+
(ref.cast_desc (ref $struct)
1455+
(ref.as_non_null
1456+
(local.get $null)
1457+
)
1458+
(struct.new $desc)
1459+
)
1460+
)
1461+
)
13831462
)

0 commit comments

Comments
 (0)