Skip to content

Commit dd3091c

Browse files
authored
Fix OptimizeInstructions on null trap of struct.set (#5449)
StructSet cannot be dropped.
1 parent ed3bf4f commit dd3091c

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

src/ir/drop.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,23 @@ Expression* getDroppedChildrenAndAppend(Expression* curr,
5959
if (effects.hasUnremovableSideEffects() || curr->is<If>() ||
6060
curr->is<Try>() || curr->is<Pop>() ||
6161
BranchUtils::getDefinedName(curr).is()) {
62-
return builder.makeSequence(builder.makeDrop(curr), last);
62+
// If curr is concrete we must drop it. Or, if it is unreachable or none,
63+
// then we can leave it as it is.
64+
if (curr->type.isConcrete()) {
65+
curr = builder.makeDrop(curr);
66+
}
67+
return builder.makeSequence(curr, last);
6368
}
6469

6570
std::vector<Expression*> contents;
6671
for (auto* child : ChildIterator(curr)) {
6772
if (!EffectAnalyzer(options, wasm, child).hasUnremovableSideEffects()) {
6873
continue;
6974
}
75+
// See above.
7076
if (child->type.isConcrete()) {
7177
contents.push_back(builder.makeDrop(child));
7278
} else {
73-
// The child is unreachable, or none (none is possible as a child of a
74-
// block or loop, etc.); in both cases we do not need a drop.
7579
contents.push_back(child);
7680
}
7781
}

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

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@
2828

2929
(type $B (struct_subtype (field i32) (field i32) (field f32) $A))
3030

31+
;; CHECK: (type $void (func))
32+
3133
;; CHECK: (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B))
34+
;; NOMNL: (type $void (func))
35+
3236
;; NOMNL: (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B))
3337
(type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B))
3438

3539
(type $empty (struct))
3640

37-
;; CHECK: (type $void (func))
38-
3941
;; CHECK: (type $C (struct_subtype (field i32) (field i32) (field f64) $A))
40-
;; NOMNL: (type $void (func))
41-
4242
;; NOMNL: (type $C (struct_subtype (field i32) (field i32) (field f64) $A))
4343
(type $C (struct_subtype (field i32) (field i32) (field f64) $A))
4444

@@ -3157,4 +3157,39 @@
31573157
)
31583158
)
31593159
)
3160+
3161+
;; CHECK: (func $struct.set.null.fallthrough (type $void)
3162+
;; CHECK-NEXT: (local $temp (ref null $struct))
3163+
;; CHECK-NEXT: (struct.set $struct $i8
3164+
;; CHECK-NEXT: (local.tee $temp
3165+
;; CHECK-NEXT: (ref.null none)
3166+
;; CHECK-NEXT: )
3167+
;; CHECK-NEXT: (i32.const 100)
3168+
;; CHECK-NEXT: )
3169+
;; CHECK-NEXT: (unreachable)
3170+
;; CHECK-NEXT: )
3171+
;; NOMNL: (func $struct.set.null.fallthrough (type $void)
3172+
;; NOMNL-NEXT: (local $temp (ref null $struct))
3173+
;; NOMNL-NEXT: (struct.set $struct $i8
3174+
;; NOMNL-NEXT: (local.tee $temp
3175+
;; NOMNL-NEXT: (ref.null none)
3176+
;; NOMNL-NEXT: )
3177+
;; NOMNL-NEXT: (i32.const 100)
3178+
;; NOMNL-NEXT: )
3179+
;; NOMNL-NEXT: (unreachable)
3180+
;; NOMNL-NEXT: )
3181+
(func $struct.set.null.fallthrough
3182+
(local $temp (ref null $struct))
3183+
;; The value falling through the tee shows the local.set will trap. We can
3184+
;; append an unreachable after it. While doing so we must not emit a drop of
3185+
;; the struct.set (which would be valid for a struct.get etc.).
3186+
(struct.set $struct 0
3187+
(local.tee $temp
3188+
(ref.as_non_null
3189+
(ref.null none)
3190+
)
3191+
)
3192+
(i32.const 100)
3193+
)
3194+
)
31603195
)

0 commit comments

Comments
 (0)