Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,17 @@ struct OptimizeInstructions
// (ref.cast (ref T) ..)
//
if (auto* as = curr->ref->dynCast<RefAs>(); as && as->op == RefAsNonNull) {
if (curr->desc) {
// There is another child here, whose effects we must consider (the same
// ordering situation as in skipNonNullCast: we want to move a trap on
// null past later children).
auto& options = getPassRunner()->options;
EffectAnalyzer descEffects(options, *getModule(), curr->desc);
ShallowEffectAnalyzer movingEffects(options, *getModule(), curr->ref);
if (descEffects.invalidates(movingEffects)) {
return;
}
}
curr->ref = as->value;
curr->type = curr->type.with(NonNullable);
}
Expand Down
113 changes: 96 additions & 17 deletions test/lit/passes/optimize-instructions-desc.wast
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
(type $struct-i32.desc (describes $struct-i32) (struct))
)

;; CHECK: (import "" "" (func $effect (type $6)))
;; NTRAP: (import "" "" (func $effect (type $6)))
;; CHECK: (import "" "" (func $effect (type $4)))
;; NTRAP: (import "" "" (func $effect (type $4)))
(import "" "" (func $effect))

;; CHECK: (func $trap-null-desc (type $10) (result (ref (exact $struct)))
Expand Down Expand Up @@ -128,12 +128,12 @@
)
)

;; CHECK: (func $cast-desc-null-desc (type $6)
;; CHECK: (func $cast-desc-null-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-null-desc (type $6)
;; NTRAP: (func $cast-desc-null-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (unreachable)
;; NTRAP-NEXT: )
Expand Down Expand Up @@ -375,7 +375,7 @@
)
)

;; CHECK: (func $cast-desc-wrong-desc (type $6)
;; CHECK: (func $cast-desc-wrong-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
;; CHECK-NEXT: (struct.new_default_desc $struct
Expand All @@ -385,7 +385,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-wrong-desc (type $6)
;; NTRAP: (func $cast-desc-wrong-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref (exact $struct)))
;; NTRAP-NEXT: (struct.new_default_desc $struct
Expand All @@ -409,7 +409,7 @@
)
)

;; CHECK: (func $cast-desc-wrong-desc-effects (type $6)
;; CHECK: (func $cast-desc-wrong-desc-effects (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
;; CHECK-NEXT: (block (result (ref (exact $struct)))
Expand All @@ -425,7 +425,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-wrong-desc-effects (type $6)
;; NTRAP: (func $cast-desc-wrong-desc-effects (type $4)
;; NTRAP-NEXT: (local $0 (ref (exact $struct)))
;; NTRAP-NEXT: (local $1 (ref (exact $desc)))
;; NTRAP-NEXT: (drop
Expand Down Expand Up @@ -497,9 +497,11 @@
;; CHECK: (func $cast-desc-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc (ref $sub)
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (block (result anyref)
;; CHECK-NEXT: (call $effect)
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref $sub.desc))
;; CHECK-NEXT: (call $effect)
Expand All @@ -511,9 +513,11 @@
;; NTRAP: (func $cast-desc-weaker-nondesc-child-effects (type $14) (param $ref anyref) (param $desc (ref $sub.desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc (ref $sub)
;; NTRAP-NEXT: (block (result anyref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (block (result anyref)
;; NTRAP-NEXT: (call $effect)
;; NTRAP-NEXT: (local.get $ref)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (block (result (ref $sub.desc))
;; NTRAP-NEXT: (call $effect)
Expand All @@ -524,7 +528,8 @@
;; NTRAP-NEXT: )
(func $cast-desc-weaker-nondesc-child-effects (param $ref anyref) (param $desc (ref $sub.desc))
(drop
;; Same, but with effects.
;; Same, but with effects. Due to ordering, we cannot remove the inner
;; cast (which turns into ref.as_non_null).
(ref.cast_desc (ref $sub)
(ref.cast (ref any)
(block (result anyref)
Expand Down Expand Up @@ -1073,7 +1078,7 @@
)
)

;; CHECK: (func $cast-desc-unreachable-desc (type $6)
;; CHECK: (func $cast-desc-unreachable-desc (type $4)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
;; CHECK-NEXT: (drop
Expand All @@ -1086,7 +1091,7 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $cast-desc-unreachable-desc (type $6)
;; NTRAP: (func $cast-desc-unreachable-desc (type $4)
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block ;; (replaces unreachable RefCast we can't emit)
;; NTRAP-NEXT: (drop
Expand Down Expand Up @@ -1380,4 +1385,78 @@
)
)
)

;; CHECK: (func $ref.cast_desc-ref.as_non_null (type $4)
;; CHECK-NEXT: (local $null (ref null $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc (ref $struct)
;; CHECK-NEXT: (ref.as_non_null
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block (result (ref null $desc))
;; CHECK-NEXT: (return)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast_desc (ref (exact $struct))
;; CHECK-NEXT: (local.get $null)
;; CHECK-NEXT: (struct.new_default $desc)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; NTRAP: (func $ref.cast_desc-ref.as_non_null (type $4)
;; NTRAP-NEXT: (local $null (ref null $struct))
;; NTRAP-NEXT: (local $1 (ref $struct))
;; NTRAP-NEXT: (local $2 (ref null $desc))
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (block (result (ref $struct))
;; NTRAP-NEXT: (local.set $1
;; NTRAP-NEXT: (ref.as_non_null
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.set $2
;; NTRAP-NEXT: (block (result (ref null $desc))
;; NTRAP-NEXT: (return)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (local.get $1)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: (drop
;; NTRAP-NEXT: (ref.cast_desc (ref (exact $struct))
;; NTRAP-NEXT: (local.get $null)
;; NTRAP-NEXT: (struct.new_default $desc)
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
;; NTRAP-NEXT: )
(func $ref.cast_desc-ref.as_non_null
(local $null (ref null $struct))
;; We read a null local and cast it to non-null, trapping. The ref.cast_desc
;; would trap on null anyhow, so it seems we can remove the ref.as_non_null,
;; but doing so would allow us to reach the block, which returns *before* the
;; ref.cast_desc would trap.
(drop
(ref.cast_desc (ref $struct)
(ref.as_non_null
(local.get $null)
)
;; Hide the return in a block, otherwise we'd skip unreachable code.
(block (result (ref null $desc))
(return)
)
)
)
;; As above, but without dangerous effects: we can remove the
;; ref.as_non_null.
(drop
(ref.cast_desc (ref $struct)
(ref.as_non_null
(local.get $null)
)
(struct.new $desc)
)
)
)
)
Loading