Skip to content

Commit 91114e6

Browse files
authored
GlobalStructInference: Add missing ReFinalize (#5898)
1 parent 73bbbab commit 91114e6

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

src/passes/GlobalStructInference.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "ir/module-utils.h"
5353
#include "ir/properties.h"
5454
#include "ir/subtypes.h"
55+
#include "ir/utils.h"
5556
#include "pass.h"
5657
#include "wasm-builder.h"
5758
#include "wasm.h"
@@ -221,6 +222,8 @@ struct GlobalStructInference : public Pass {
221222

222223
FunctionOptimizer(GlobalStructInference& parent) : parent(parent) {}
223224

225+
bool refinalize = false;
226+
224227
void visitStructGet(StructGet* curr) {
225228
auto type = curr->ref->type;
226229
if (type == Type::unreachable) {
@@ -262,9 +265,16 @@ struct GlobalStructInference : public Pass {
262265
// will unlock those other optimizations. Note we must trap if the ref
263266
// is null, so add RefAsNonNull here.
264267
auto global = globals[0];
268+
auto globalType = wasm.getGlobal(global)->type;
269+
if (globalType != curr->ref->type) {
270+
// The struct.get will now read from something of the type of the
271+
// global, which is different, so the field being read might be
272+
// refined, which could change the struct.get's type.
273+
refinalize = true;
274+
}
265275
curr->ref = builder.makeSequence(
266276
builder.makeDrop(builder.makeRefAs(RefAsNonNull, curr->ref)),
267-
builder.makeGlobalGet(global, wasm.getGlobal(globals[0])->type));
277+
builder.makeGlobalGet(global, globalType));
268278
return;
269279
}
270280

@@ -367,6 +377,12 @@ struct GlobalStructInference : public Pass {
367377
builder.makeConstantExpression(values[1])));
368378
}
369379

380+
void visitFunction(Function* func) {
381+
if (refinalize) {
382+
ReFinalize().walkFunctionInModule(func, getModule());
383+
}
384+
}
385+
370386
private:
371387
GlobalStructInference& parent;
372388
};

test/lit/passes/gsi.wast

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,3 +1390,50 @@
13901390
)
13911391
)
13921392
)
1393+
1394+
(module
1395+
(rec
1396+
;; CHECK: (rec
1397+
;; CHECK-NEXT: (type $A (struct (field funcref)))
1398+
(type $A (struct (field funcref)))
1399+
;; CHECK: (type $B (sub $A (struct (field (ref func)))))
1400+
(type $B (sub $A (struct (field (ref func)))))
1401+
)
1402+
1403+
;; CHECK: (type $2 (func (param (ref null $A) (ref null $B)) (result funcref)))
1404+
1405+
;; CHECK: (global $global (ref $B) (struct.new $B
1406+
;; CHECK-NEXT: (ref.func $func)
1407+
;; CHECK-NEXT: ))
1408+
(global $global (ref $B) (struct.new $B
1409+
(ref.func $func)
1410+
))
1411+
1412+
;; CHECK: (func $func (type $2) (param $a (ref null $A)) (param $b (ref null $B)) (result funcref)
1413+
;; CHECK-NEXT: (struct.get $B 0
1414+
;; CHECK-NEXT: (block (result (ref $B))
1415+
;; CHECK-NEXT: (drop
1416+
;; CHECK-NEXT: (ref.as_non_null
1417+
;; CHECK-NEXT: (local.tee $a
1418+
;; CHECK-NEXT: (local.get $b)
1419+
;; CHECK-NEXT: )
1420+
;; CHECK-NEXT: )
1421+
;; CHECK-NEXT: )
1422+
;; CHECK-NEXT: (global.get $global)
1423+
;; CHECK-NEXT: )
1424+
;; CHECK-NEXT: )
1425+
;; CHECK-NEXT: )
1426+
(func $func (param $a (ref null $A)) (param $b (ref null $B)) (result funcref)
1427+
(struct.get $A 0
1428+
;; We can infer that we read from $global here, since it is the only place
1429+
;; a $B is created (the tee in the middle to $A does not confuse us).
1430+
;; After that, the struct.get will be reading a global.get of $global,
1431+
;; which is of type $B, and compared to $A from before we will read a more
1432+
;; refined type from the field, ref func vs funcref, which must be updated
1433+
;; in the IR.
1434+
(local.tee $a
1435+
(local.get $b)
1436+
)
1437+
)
1438+
)
1439+
)

0 commit comments

Comments
 (0)