Skip to content

Commit fd3f58a

Browse files
committed
fix
1 parent 0e2eb12 commit fd3f58a

File tree

2 files changed

+86
-30
lines changed

2 files changed

+86
-30
lines changed

src/passes/OptimizeInstructions.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,13 +1800,18 @@ struct OptimizeInstructions
18001800
}
18011801

18021802
void visitRefEq(RefEq* curr) {
1803-
// The types may prove that the same reference cannot appear on both sides.
1803+
// Check for unreachability. Note we must check both the children and the
1804+
// ref.eq itself, as in e.g. visitTernary, as we only refinalize at the end,
1805+
// so unreachable children may not update the parent yet.
18041806
auto leftType = curr->left->type;
18051807
auto rightType = curr->right->type;
1806-
if (leftType == Type::unreachable || rightType == Type::unreachable) {
1808+
if (leftType == Type::unreachable || rightType == Type::unreachable ||
1809+
curr->type == Type::unreachable) {
18071810
// Leave this for DCE.
18081811
return;
18091812
}
1813+
1814+
// The types may prove that the same reference cannot appear on both sides.
18101815
auto leftHeapType = leftType.getHeapType();
18111816
auto rightHeapType = rightType.getHeapType();
18121817
auto leftIsHeapSubtype = HeapType::isSubType(leftHeapType, rightHeapType);

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

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
;; CHECK: (type $B-child (sub $B (struct (field i32) (field i32) (field f32) (field i64))))
2828
(type $B-child (sub $B (struct (field i32) (field i32) (field f32) (field i64))))
2929

30-
(type $empty (struct))
31-
3230
;; CHECK: (type $C (sub $A (struct (field i32) (field i32) (field f64))))
3331

3432
;; CHECK: (rec
@@ -37,6 +35,12 @@
3735
;; CHECK: (type $void2 (sub $void (func)))
3836

3937
;; CHECK: (type $struct.ref (struct (field funcref)))
38+
39+
;; CHECK: (type $struct_i64 (func (param structref) (result i64)))
40+
41+
;; CHECK: (type $empty (struct))
42+
(type $empty (struct))
43+
4044
(type $struct.ref (struct (field funcref)))
4145

4246
(type $C (sub $A (struct (field i32) (field i32) (field f64))))
@@ -48,7 +52,6 @@
4852
(type $void2 (sub $void (func)))
4953
)
5054

51-
;; CHECK: (type $struct_i64 (func (param structref) (result i64)))
5255
(type $struct_i64 (func (param (ref null struct)) (result i64)))
5356

5457
;; CHECK: (import "env" "get-i32" (func $get-i32 (type $8) (result i32)))
@@ -289,7 +292,7 @@
289292
)
290293
)
291294

292-
;; CHECK: (func $unneeded_unreachability (type $5)
295+
;; CHECK: (func $unneeded_unreachability (type $4)
293296
;; CHECK-NEXT: (drop
294297
;; CHECK-NEXT: (ref.test (ref func)
295298
;; CHECK-NEXT: (unreachable)
@@ -477,11 +480,11 @@
477480
)
478481
)
479482

480-
;; CHECK: (func $nothing (type $5)
483+
;; CHECK: (func $nothing (type $4)
481484
;; CHECK-NEXT: )
482485
(func $nothing)
483486

484-
;; CHECK: (func $ref-eq-corner-cases (type $4) (param $x eqref)
487+
;; CHECK: (func $ref-eq-corner-cases (type $5) (param $x eqref)
485488
;; CHECK-NEXT: (drop
486489
;; CHECK-NEXT: (ref.eq
487490
;; CHECK-NEXT: (block (result eqref)
@@ -568,7 +571,7 @@
568571
)
569572
)
570573

571-
;; CHECK: (func $ref-eq-ref-cast (type $4) (param $x eqref)
574+
;; CHECK: (func $ref-eq-ref-cast (type $5) (param $x eqref)
572575
;; CHECK-NEXT: (drop
573576
;; CHECK-NEXT: (ref.eq
574577
;; CHECK-NEXT: (local.get $x)
@@ -800,7 +803,7 @@
800803
)
801804
)
802805

803-
;; CHECK: (func $ref-cast-squared (type $4) (param $x eqref)
806+
;; CHECK: (func $ref-cast-squared (type $5) (param $x eqref)
804807
;; CHECK-NEXT: (drop
805808
;; CHECK-NEXT: (ref.cast (ref null $struct)
806809
;; CHECK-NEXT: (local.get $x)
@@ -817,7 +820,7 @@
817820
)
818821
)
819822
)
820-
;; CHECK: (func $ref-cast-squared-fallthrough (type $4) (param $x eqref)
823+
;; CHECK: (func $ref-cast-squared-fallthrough (type $5) (param $x eqref)
821824
;; CHECK-NEXT: (local $1 (ref null $struct))
822825
;; CHECK-NEXT: (drop
823826
;; CHECK-NEXT: (block (result (ref null $struct))
@@ -846,7 +849,7 @@
846849
)
847850
)
848851
)
849-
;; CHECK: (func $ref-cast-cubed (type $4) (param $x eqref)
852+
;; CHECK: (func $ref-cast-cubed (type $5) (param $x eqref)
850853
;; CHECK-NEXT: (drop
851854
;; CHECK-NEXT: (ref.cast (ref null $struct)
852855
;; CHECK-NEXT: (local.get $x)
@@ -865,7 +868,7 @@
865868
)
866869
)
867870
)
868-
;; CHECK: (func $ref-cast-squared-different (type $4) (param $x eqref)
871+
;; CHECK: (func $ref-cast-squared-different (type $5) (param $x eqref)
869872
;; CHECK-NEXT: (drop
870873
;; CHECK-NEXT: (ref.cast nullref
871874
;; CHECK-NEXT: (local.get $x)
@@ -884,7 +887,7 @@
884887
)
885888
)
886889

887-
;; CHECK: (func $ref-eq-null (type $4) (param $x eqref)
890+
;; CHECK: (func $ref-eq-null (type $5) (param $x eqref)
888891
;; CHECK-NEXT: (drop
889892
;; CHECK-NEXT: (ref.is_null
890893
;; CHECK-NEXT: (local.get $x)
@@ -1560,7 +1563,7 @@
15601563
)
15611564
)
15621565

1563-
;; CHECK: (func $ref-cast-static-null (type $5)
1566+
;; CHECK: (func $ref-cast-static-null (type $4)
15641567
;; CHECK-NEXT: (local $a (ref null $A))
15651568
;; CHECK-NEXT: (drop
15661569
;; CHECK-NEXT: (ref.null none)
@@ -1703,7 +1706,7 @@
17031706
)
17041707
)
17051708

1706-
;; CHECK: (func $ref-cast-static-squared (type $4) (param $x eqref)
1709+
;; CHECK: (func $ref-cast-static-squared (type $5) (param $x eqref)
17071710
;; CHECK-NEXT: (drop
17081711
;; CHECK-NEXT: (ref.cast (ref null $A)
17091712
;; CHECK-NEXT: (local.get $x)
@@ -1746,7 +1749,7 @@
17461749
)
17471750
)
17481751

1749-
;; CHECK: (func $ref-cast-static-many (type $4) (param $x eqref)
1752+
;; CHECK: (func $ref-cast-static-many (type $5) (param $x eqref)
17501753
;; CHECK-NEXT: (drop
17511754
;; CHECK-NEXT: (ref.cast (ref null $B-child)
17521755
;; CHECK-NEXT: (local.get $x)
@@ -1837,7 +1840,7 @@
18371840
)
18381841
)
18391842

1840-
;; CHECK: (func $ref-cast-static-very-many (type $4) (param $x eqref)
1843+
;; CHECK: (func $ref-cast-static-very-many (type $5) (param $x eqref)
18411844
;; CHECK-NEXT: (drop
18421845
;; CHECK-NEXT: (ref.cast (ref null $B-child)
18431846
;; CHECK-NEXT: (local.get $x)
@@ -1875,7 +1878,7 @@
18751878
)
18761879
)
18771880

1878-
;; CHECK: (func $ref-cast-static-fallthrough-remaining (type $4) (param $x eqref)
1881+
;; CHECK: (func $ref-cast-static-fallthrough-remaining (type $5) (param $x eqref)
18791882
;; CHECK-NEXT: (drop
18801883
;; CHECK-NEXT: (block (result (ref null $B))
18811884
;; CHECK-NEXT: (call $ref-cast-static-fallthrough-remaining
@@ -1910,7 +1913,7 @@
19101913
)
19111914
)
19121915

1913-
;; CHECK: (func $ref-cast-static-fallthrough-remaining-child (type $4) (param $x eqref)
1916+
;; CHECK: (func $ref-cast-static-fallthrough-remaining-child (type $5) (param $x eqref)
19141917
;; CHECK-NEXT: (drop
19151918
;; CHECK-NEXT: (ref.cast (ref null $B)
19161919
;; CHECK-NEXT: (block (result eqref)
@@ -2016,7 +2019,7 @@
20162019
)
20172020
)
20182021

2019-
;; CHECK: (func $ref-cast-static-squared-impossible (type $4) (param $x eqref)
2022+
;; CHECK: (func $ref-cast-static-squared-impossible (type $5) (param $x eqref)
20202023
;; CHECK-NEXT: (drop
20212024
;; CHECK-NEXT: (ref.cast nullref
20222025
;; CHECK-NEXT: (local.get $x)
@@ -2755,7 +2758,7 @@
27552758
)
27562759
)
27572760

2758-
;; CHECK: (func $struct.set.null.fallthrough (type $5)
2761+
;; CHECK: (func $struct.set.null.fallthrough (type $4)
27592762
;; CHECK-NEXT: (local $temp (ref null $struct))
27602763
;; CHECK-NEXT: (block ;; (replaces unreachable StructSet we can't emit)
27612764
;; CHECK-NEXT: (drop
@@ -2784,7 +2787,7 @@
27842787
)
27852788
)
27862789

2787-
;; CHECK: (func $set.array.null (type $5)
2790+
;; CHECK: (func $set.array.null (type $4)
27882791
;; CHECK-NEXT: (local $temp (ref none))
27892792
;; CHECK-NEXT: (block ;; (replaces unreachable ArraySet we can't emit)
27902793
;; CHECK-NEXT: (drop
@@ -2856,7 +2859,7 @@
28562859
)
28572860
)
28582861

2859-
;; CHECK: (func $refinalize.select.arm.flip (type $5)
2862+
;; CHECK: (func $refinalize.select.arm.flip (type $4)
28602863
;; CHECK-NEXT: (drop
28612864
;; CHECK-NEXT: (block (result (ref (exact $void2)))
28622865
;; CHECK-NEXT: (ref.func $func.arm.2)
@@ -2995,7 +2998,7 @@
29952998
)
29962999
)
29973000

2998-
;; CHECK: (func $ref.test-fallthrough (type $5)
3001+
;; CHECK: (func $ref.test-fallthrough (type $4)
29993002
;; CHECK-NEXT: (local $A (ref $A))
30003003
;; CHECK-NEXT: (drop
30013004
;; CHECK-NEXT: (block (result i32)
@@ -3084,7 +3087,7 @@
30843087
)
30853088
)
30863089

3087-
;; CHECK: (func $gc_to_unreachable_in_added_constants (type $5)
3090+
;; CHECK: (func $gc_to_unreachable_in_added_constants (type $4)
30883091
;; CHECK-NEXT: (drop
30893092
;; CHECK-NEXT: (i32.wrap_i64
30903093
;; CHECK-NEXT: (i64.add
@@ -3174,7 +3177,7 @@
31743177
)
31753178
)
31763179

3177-
;; CHECK: (func $struct.new (type $5)
3180+
;; CHECK: (func $struct.new (type $4)
31783181
;; CHECK-NEXT: (drop
31793182
;; CHECK-NEXT: (block (result (ref (exact $struct)))
31803183
;; CHECK-NEXT: (drop
@@ -3259,7 +3262,7 @@
32593262
)
32603263
)
32613264

3262-
;; CHECK: (func $array.new (type $5)
3265+
;; CHECK: (func $array.new (type $4)
32633266
;; CHECK-NEXT: (drop
32643267
;; CHECK-NEXT: (block (result (ref (exact $array)))
32653268
;; CHECK-NEXT: (drop
@@ -3328,7 +3331,7 @@
33283331
)
33293332
)
33303333

3331-
;; CHECK: (func $array.new_fixed (type $5)
3334+
;; CHECK: (func $array.new_fixed (type $4)
33323335
;; CHECK-NEXT: (local $0 i32)
33333336
;; CHECK-NEXT: (local $1 i32)
33343337
;; CHECK-NEXT: (drop
@@ -3436,7 +3439,7 @@
34363439
)
34373440
)
34383441

3439-
;; CHECK: (func $array.new_fixed_fallthrough (type $5)
3442+
;; CHECK: (func $array.new_fixed_fallthrough (type $4)
34403443
;; CHECK-NEXT: (local $0 i32)
34413444
;; CHECK-NEXT: (local $1 i32)
34423445
;; CHECK-NEXT: (local $2 i32)
@@ -3689,4 +3692,52 @@
36893692
(i32.const 0)
36903693
)
36913694
)
3695+
3696+
;; CHECK: (func $comp-i31-struct-unreachable-if (type $4)
3697+
;; CHECK-NEXT: (ref.eq
3698+
;; CHECK-NEXT: (ref.i31
3699+
;; CHECK-NEXT: (if (result i32)
3700+
;; CHECK-NEXT: (unreachable)
3701+
;; CHECK-NEXT: (then
3702+
;; CHECK-NEXT: (i32.const 0)
3703+
;; CHECK-NEXT: )
3704+
;; CHECK-NEXT: (else
3705+
;; CHECK-NEXT: (i32.const 1)
3706+
;; CHECK-NEXT: )
3707+
;; CHECK-NEXT: )
3708+
;; CHECK-NEXT: )
3709+
;; CHECK-NEXT: (struct.new_default $empty)
3710+
;; CHECK-NEXT: )
3711+
;; CHECK-NEXT: (unreachable)
3712+
;; CHECK-NEXT: )
3713+
(func $comp-i31-struct-unreachable-if
3714+
;; The if is unreachable because of its condition, however, it has reachable
3715+
;; arms and is declared with a concrete type, so it only becomes unreachable
3716+
;; when we refinalize (which can happen if we pull the ref.i31 out of the
3717+
;; arms). We must be careful when handling the ref.eq: if we don't realize
3718+
;; it is unreachable, we might think we can prove it returns 0 (since one
3719+
;; arm is i31, the other a struct, both non-nullable, and hence there is no
3720+
;; overlap). If we do that, and emit a 0, we'd be turning an unreachable
3721+
;; into a concrete type, and nothing pops that type off the stack, so we
3722+
;; would fail to validate.
3723+
(ref.eq
3724+
(if (result (ref i31))
3725+
(unreachable)
3726+
(then
3727+
(ref.i31
3728+
(i32.const 0)
3729+
)
3730+
)
3731+
(else
3732+
(ref.i31
3733+
(i32.const 1)
3734+
)
3735+
)
3736+
)
3737+
(struct.new_default $empty)
3738+
)
3739+
;; Nothing reads the ref.eq on the stack.
3740+
(unreachable)
3741+
)
36923742
)
3743+

0 commit comments

Comments
 (0)