Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracle chaining sketch #5853

Draft
wants to merge 230 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
230 commits
Select commit Hold shift + click to select a range
8c931cd
yolo
kripken Jul 12, 2023
684a6da
work
kripken Jul 12, 2023
a0c7e99
work
kripken Jul 12, 2023
d5005ec
work
kripken Jul 12, 2023
0be5b74
work
kripken Jul 12, 2023
6fa6d68
work
kripken Jul 12, 2023
7ced207
work
kripken Jul 12, 2023
99c399c
start
kripken Jul 12, 2023
e6600c6
start
kripken Jul 12, 2023
1a38e39
fail
kripken Jul 12, 2023
ea17a61
problem
kripken Jul 12, 2023
23b476d
start to work
kripken Jul 12, 2023
5763c62
work
kripken Jul 13, 2023
b5db8e3
work
kripken Jul 13, 2023
f92f678
work
kripken Jul 13, 2023
da834db
work
kripken Jul 13, 2023
b35fd92
work
kripken Jul 13, 2023
1bd1708
work
kripken Jul 13, 2023
0ad0de7
work
kripken Jul 13, 2023
eabe345
start
kripken Jul 13, 2023
3c970af
work
kripken Jul 13, 2023
1a31259
big refcator?
kripken Jul 13, 2023
2ed5b85
big refcator?
kripken Jul 13, 2023
b27214c
work
kripken Jul 13, 2023
aadd858
work
kripken Jul 13, 2023
3ca0f6b
test
kripken Jul 13, 2023
6fff684
work
kripken Jul 13, 2023
6475fec
work
kripken Jul 13, 2023
c6e3f24
work
kripken Jul 13, 2023
8495b51
work
kripken Jul 13, 2023
1d158fb
work
kripken Jul 13, 2023
c2e9882
work
kripken Jul 13, 2023
7f031ee
safer
kripken Jul 13, 2023
62ed94a
safer
kripken Jul 13, 2023
8321582
fix
kripken Jul 13, 2023
7afd5ff
work
kripken Jul 13, 2023
a690d6c
moar.fuzz
kripken Jul 13, 2023
d05192e
test
kripken Jul 13, 2023
e7ed443
test
kripken Jul 13, 2023
194220b
test
kripken Jul 13, 2023
5de9d69
clean
kripken Jul 13, 2023
dd11d35
TODO
kripken Jul 13, 2023
8e1d532
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 17, 2023
ce5a16e
work
kripken Jul 18, 2023
04b2b66
more
kripken Jul 18, 2023
adba60d
improve
kripken Jul 18, 2023
390d281
test
kripken Jul 18, 2023
721840a
test
kripken Jul 18, 2023
61ca85c
callsites
kripken Jul 18, 2023
4cf7877
generalize?
kripken Jul 18, 2023
806935e
parallize
kripken Jul 18, 2023
208c3a7
yolo
kripken Jul 18, 2023
8e9085a
builds
kripken Jul 18, 2023
ac7d99a
fix
kripken Jul 18, 2023
650e5d7
build
kripken Jul 18, 2023
4d20b66
fixx
kripken Jul 18, 2023
4f62ddf
text
kripken Jul 18, 2023
ba3215b
format
kripken Jul 18, 2023
b437d64
start reffactor
kripken Jul 18, 2023
fbd49cc
format
kripken Jul 18, 2023
b5cb77c
format
kripken Jul 18, 2023
eb616fd
work
kripken Jul 18, 2023
140fb11
format
kripken Jul 18, 2023
a9e111b
fix
kripken Jul 18, 2023
aeb4f73
simpl
kripken Jul 18, 2023
9a8ac1f
formt
kripken Jul 18, 2023
d43c60d
wkr
kripken Jul 18, 2023
fa25919
yolo
kripken Jul 18, 2023
d2e8307
why.why.why
kripken Jul 19, 2023
6700b25
test
kripken Jul 19, 2023
911e0ab
work
kripken Jul 19, 2023
ed851e3
fix
kripken Jul 19, 2023
9cbdb92
work
kripken Jul 19, 2023
645c649
fix
kripken Jul 19, 2023
d6d64bf
handle unreachable code
kripken Jul 19, 2023
c114abf
comment
kripken Jul 19, 2023
262e1e3
moar.gufa
kripken Jul 19, 2023
1eee86f
moar.gufa
kripken Jul 19, 2023
517c958
fix
kripken Jul 19, 2023
73775ae
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 19, 2023
df4350f
leanup
kripken Jul 19, 2023
d4a7568
comments
kripken Jul 19, 2023
cb05934
comments
kripken Jul 19, 2023
7e44b05
fix
kripken Jul 19, 2023
4f3d5fb
test
kripken Jul 19, 2023
65829a8
work
kripken Jul 19, 2023
eff39f8
errors
kripken Jul 19, 2023
7b02072
bettr
kripken Jul 19, 2023
ddb9559
fix
kripken Jul 19, 2023
6fe72f3
Merge remote-tracking branch 'origin/main' into analysis.cfg.block.in…
kripken Jul 20, 2023
c55f6cb
refactor
kripken Jul 20, 2023
760d28b
fixes
kripken Jul 20, 2023
edd5cf5
const
kripken Jul 20, 2023
63b06e5
Merge remote-tracking branch 'origin/analysis.cfg.block.indexes' into…
kripken Jul 20, 2023
8c71e8b
work
kripken Jul 20, 2023
f58db54
fix
kripken Jul 20, 2023
aa1d167
fix
kripken Jul 20, 2023
254e960
format
kripken Jul 20, 2023
6b4299c
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 20, 2023
4911f8e
yolo
kripken Jul 20, 2023
b5dfd0d
work
kripken Jul 20, 2023
8c4c8c1
moar
kripken Jul 20, 2023
f842298
fix
kripken Jul 20, 2023
434ba3c
works
kripken Jul 20, 2023
9723f4b
array
kripken Jul 20, 2023
2eb5860
start
kripken Jul 20, 2023
787cc58
format
kripken Jul 20, 2023
a85cc07
work
kripken Jul 20, 2023
f6e5415
work
kripken Jul 20, 2023
1971be0
test
kripken Jul 20, 2023
dba22c9
yolo
kripken Jul 20, 2023
2ff404c
yolo
kripken Jul 20, 2023
e095173
test
kripken Jul 20, 2023
354d9f0
redo
kripken Jul 20, 2023
3d284c9
format
kripken Jul 20, 2023
029a741
fix
kripken Jul 20, 2023
8252dd5
undo
kripken Jul 20, 2023
3c6828f
refactor
kripken Jul 20, 2023
94abc06
comment
kripken Jul 20, 2023
0d7a2b3
comment
kripken Jul 20, 2023
ae13069
comment
kripken Jul 20, 2023
ef30356
prepare
kripken Jul 21, 2023
6c23d3a
prep
kripken Jul 21, 2023
951ede1
work
kripken Jul 21, 2023
a93e9f3
work
kripken Jul 21, 2023
7eeb5d1
builds
kripken Jul 21, 2023
fae9c90
work on test
kripken Jul 21, 2023
c57bac7
test
kripken Jul 21, 2023
b1d391f
test
kripken Jul 21, 2023
a995b63
test
kripken Jul 21, 2023
304843d
fix
kripken Jul 21, 2023
47a6e4b
work
kripken Jul 21, 2023
b1bad87
ferfact
kripken Jul 21, 2023
8112b3c
builds
kripken Jul 21, 2023
ebb6f74
work.hard
kripken Jul 21, 2023
2e5772b
wo
kripken Jul 21, 2023
6c818e6
work
kripken Jul 21, 2023
ca5db04
fies
kripken Jul 21, 2023
9d59f44
fix
kripken Jul 21, 2023
a58a99f
format
kripken Jul 21, 2023
9715cee
work
kripken Jul 21, 2023
136e367
work
kripken Jul 21, 2023
6c11862
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 21, 2023
f379809
work
kripken Jul 21, 2023
0528ead
test
kripken Jul 21, 2023
5e4bdb6
test
kripken Jul 21, 2023
475dc4b
test
kripken Jul 24, 2023
321731d
big refactor
kripken Jul 24, 2023
c8a12ec
fix
kripken Jul 24, 2023
ecf80aa
format
kripken Jul 24, 2023
0d94596
refactor
kripken Jul 24, 2023
51cede7
refactor.done
kripken Jul 24, 2023
48af605
refactor
kripken Jul 24, 2023
31fbca7
work
kripken Jul 24, 2023
c59eb9d
test
kripken Jul 24, 2023
5aad6cb
test
kripken Jul 24, 2023
0e54827
bettr
kripken Jul 24, 2023
c76b9fb
test
kripken Jul 24, 2023
87771d1
work
kripken Jul 24, 2023
cacb33d
test
kripken Jul 24, 2023
9f3320c
work
kripken Jul 24, 2023
4ef3346
work.no.test
kripken Jul 24, 2023
2cdecd4
work.no.test
kripken Jul 24, 2023
e6f19fc
test
kripken Jul 25, 2023
69aeefe
test
kripken Jul 25, 2023
e2a1e8b
format
kripken Jul 25, 2023
7031063
comment
kripken Jul 26, 2023
45bd91b
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 26, 2023
830d36c
work
kripken Jul 26, 2023
a1be061
Merge remote-tracking branch 'origin/main' into gufa.cast-all-the-things
kripken Jul 27, 2023
867727b
work
kripken Jul 27, 2023
aea2d72
fix
kripken Jul 27, 2023
c326b16
work
kripken Jul 27, 2023
971c996
test
kripken Jul 27, 2023
835ebc8
format
kripken Jul 27, 2023
5cc2a49
comment
kripken Jul 27, 2023
dfd5ec0
fix
kripken Jul 27, 2023
916931b
format
kripken Jul 27, 2023
aa50361
fix
kripken Jul 27, 2023
71d5ee7
comment
kripken Jul 27, 2023
9d15a28
Merge remote-tracking branch 'origin/gufa.cast-all-the-things' into g…
kripken Jul 27, 2023
e751250
fix
kripken Jul 27, 2023
ab8c492
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 27, 2023
b8fbfbc
Merge remote-tracking branch 'origin/main' into gufa.o.c.c
kripken Jul 31, 2023
e0d0cb9
undo
kripken Jul 31, 2023
e6f2579
undo
kripken Jul 31, 2023
a53642d
text
kripken Jul 31, 2023
6cf4db0
text
kripken Jul 31, 2023
d9c9125
bettr
kripken Jul 31, 2023
f006b0a
bettr
kripken Jul 31, 2023
2e46511
bettr
kripken Jul 31, 2023
3c3de93
bettr
kripken Jul 31, 2023
235fd39
bettr
kripken Jul 31, 2023
bb58d61
more.fuzz
kripken Jul 31, 2023
01b9a04
bettr
kripken Jul 31, 2023
5e7d1f1
bettr
kripken Jul 31, 2023
750b245
bettr
kripken Jul 31, 2023
2d85fa5
fixes
kripken Jul 31, 2023
ca01b40
fixes
kripken Jul 31, 2023
e515911
fixes
kripken Jul 31, 2023
f2440bc
fixes
kripken Jul 31, 2023
3ae5309
fixes
kripken Jul 31, 2023
9b2757f
fixes
kripken Jul 31, 2023
785a2f1
fixes
kripken Jul 31, 2023
e77cc21
simplr
kripken Jul 31, 2023
8bd84c1
test
kripken Jul 31, 2023
0d374c3
undo
kripken Jul 31, 2023
f89faf8
feedback
kripken Aug 1, 2023
bb96be8
format
kripken Aug 1, 2023
7f82d69
test
kripken Aug 1, 2023
66b48df
feedback
kripken Aug 1, 2023
5eaac01
simplr
kripken Aug 1, 2023
a540316
bettr
kripken Aug 1, 2023
c586a58
simplr
kripken Aug 1, 2023
b0cbc6b
simplr
kripken Aug 1, 2023
cd3d47a
Update src/ir/possible-contents.cpp
kripken Aug 1, 2023
81cf0aa
Merge remote-tracking branch 'origin/gufa.o.c.c' into gufa.o.c.c
kripken Aug 1, 2023
3d7396d
Update test/lit/passes/gufa-tnh-closed.wast
kripken Aug 1, 2023
d2431bb
Update test/lit/passes/gufa-tnh-closed.wast
kripken Aug 1, 2023
f5d6b7a
add array.init_elem|data
kripken Aug 1, 2023
0975330
todo from feedback
kripken Aug 1, 2023
a8e6e31
generic oracle
kripken Aug 2, 2023
55e2635
build TNHOracle on Oracle
kripken Aug 2, 2023
bf60082
debug
kripken Aug 2, 2023
05a4420
Merge remote-tracking branch 'origin/main' into gufa.o.c.c.chaining
kripken Aug 2, 2023
6580afc
fix
kripken Aug 2, 2023
265672d
format
kripken Aug 2, 2023
7cdf809
second
kripken Aug 2, 2023
5f9018f
try.but.fail
kripken Aug 2, 2023
8e5408d
notes
kripken Aug 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
122 changes: 74 additions & 48 deletions src/ir/possible-contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1372,38 +1372,41 @@ struct TNHInfo {
std::unordered_map<Expression*, PossibleContents> inferences;
};

class TNHOracle : public ModuleUtils::ParallelFunctionAnalysis<TNHInfo> {
class TNHOracleAnalysis
: public ModuleUtils::ParallelFunctionAnalysis<TNHInfo> {
const PassOptions& options;
std::shared_ptr<const Oracle> prevOracle;

public:
using Parent = ModuleUtils::ParallelFunctionAnalysis<TNHInfo>;
TNHOracle(Module& wasm, const PassOptions& options)
TNHOracleAnalysis(Module& wasm,
const PassOptions& options,
std::shared_ptr<const Oracle> prevOracle)
: Parent(wasm,
[this, &options](Function* func, TNHInfo& info) {
scan(func, info, options);
}),
options(options) {
options(options), prevOracle(prevOracle) {

// After the scanning phase that we run in the constructor, continue to the
// second phase of analysis: inference.
infer();
}

// Get the type we inferred was possible at a location.
PossibleContents getContents(Expression* curr) {
auto naiveContents = PossibleContents::fullConeType(curr->type);

// If we inferred nothing, use the naive type.
auto iter = inferences.find(curr);
if (iter == inferences.end()) {
return naiveContents;
PossibleContents getContents(Expression* curr) const {
if (auto iter = inferences.find(curr); iter != inferences.end()) {
// We only store useful contents that improve on the naive estimate that
// uses the type in the IR.
[[maybe_unused]] auto naiveContents =
PossibleContents::fullConeType(curr->type);
auto contents = iter->second;
assert(contents != naiveContents);
return contents;
}

auto& contents = iter->second;
// We only store useful contents that improve on the naive estimate that
// uses the type in the IR.
assert(contents != naiveContents);
return contents;
// We inferred nothing ourselves, so defer to the previous oracle.
return prevOracle->getExprContents(curr);
}

private:
Expand All @@ -1424,11 +1427,38 @@ class TNHOracle : public ModuleUtils::ParallelFunctionAnalysis<TNHInfo> {
const CastParams& targetCastParams,
const analysis::CFGBlockIndexes& blockIndexes,
TNHInfo& info);

// Get the information known by the previous oracle.
PossibleContents getPrevContents(Expression* expr) {
return prevOracle->getExprContents(expr);
}
};

void TNHOracle::scan(Function* func,
TNHInfo& info,
const PassOptions& options) {
// Wraps around a TNHOracleAnalysis in order to provide a standard Oracle
// interface (this avoids multiple inheritance).
class TNHOracle : public Oracle {
TNHOracleAnalysis analysis;

public:
TNHOracle(Module& wasm,
const PassOptions& options,
std::shared_ptr<const Oracle> prevOracle)
: Oracle(wasm, options), analysis(wasm, options, prevOracle) {}

// Get the type we inferred was possible at a location.
PossibleContents getContents(Location location) const override {
if (auto* exprLoc = std::get_if<ExpressionLocation>(&location)) {
return analysis.getContents(exprLoc->expr);
}

// We do not infer about non-expression locations yet.
return PossibleContents::many();
}
};

void TNHOracleAnalysis::scan(Function* func,
TNHInfo& info,
const PassOptions& options) {
if (func->imported()) {
return;
}
Expand Down Expand Up @@ -1532,7 +1562,7 @@ void TNHOracle::scan(Function* func,
scanner.walkFunction(func);
}

void TNHOracle::infer() {
void TNHOracleAnalysis::infer() {
// Phase 2: Inside each function, optimize calls based on the cast params of
// the called function (which we noted during phase 1).
//
Expand Down Expand Up @@ -1620,7 +1650,7 @@ void TNHOracle::infer() {
}

for (auto* call : info.callRefs) {
auto targetType = call->target->type;
auto targetType = getPrevContents(call->target).getType();
if (!targetType.isRef()) {
// This is unreachable or null, and other passes will optimize that.
continue;
Expand Down Expand Up @@ -1652,7 +1682,8 @@ void TNHOracle::infer() {
// If any of our operands will fail a cast, then we will trap.
bool traps = false;
for (auto& [castIndex, castType] : targetInfo.castParams) {
auto operandType = call->operands[castIndex]->type;
auto operandType =
getPrevContents(call->operands[castIndex]).getType();
auto result = GCTypeUtils::evaluateCastCheck(operandType, castType);
if (result == GCTypeUtils::Failure) {
traps = true;
Expand Down Expand Up @@ -1733,11 +1764,12 @@ void TNHOracle::infer() {
}
}

void TNHOracle::optimizeCallCasts(Expression* call,
const ExpressionList& operands,
const CastParams& targetCastParams,
const analysis::CFGBlockIndexes& blockIndexes,
TNHInfo& info) {
void TNHOracleAnalysis::optimizeCallCasts(
Expression* call,
const ExpressionList& operands,
const CastParams& targetCastParams,
const analysis::CFGBlockIndexes& blockIndexes,
TNHInfo& info) {
// Optimize in the same basic block as the call: all instructions still in
// that block will definitely execute if the call is reached. We will do that
// by going backwards through the call's operands and fallthrough values, and
Expand Down Expand Up @@ -1773,26 +1805,15 @@ void TNHOracle::optimizeCallCasts(Expression* call,
auto* curr = operand;
while (1) {
// Note the type if it is useful.
if (castType != curr->type) {
// There are two constraints on this location: any value there must
// be of the declared type (curr->type) and also the cast type, so
// we know only their intersection can appear here.
auto declared = PossibleContents::fullConeType(curr->type);
auto intersection = PossibleContents::fullConeType(castType);
intersection.intersect(declared);
if (intersection.isConeType()) {
auto intersectionType = intersection.getType();
if (intersectionType != curr->type) {
// We inferred a more refined type.
info.inferences[curr] = intersection;
}
} else {
// Otherwise, the intersection can be a null (if the heap types are
// incompatible, but a null is allowed), or empty. We can apply
// either.
assert(intersection.isNull() || intersection.isNone());
info.inferences[curr] = intersection;
}
//
// There are two constraints on this location: what we know about it
// already (from the previous oracle), and also the cast type, so we know
// only their intersection can appear here.
auto known = getPrevContents(curr);
auto intersection = PossibleContents::fullConeType(castType);
intersection.intersect(known);
if (intersection != known) {
info.inferences[curr] = intersection;
}

auto* next = Properties::getImmediateFallthrough(curr, options, wasm);
Expand Down Expand Up @@ -1864,7 +1885,7 @@ struct Flower {
// No oracle; just use the type in the IR.
return PossibleContents::fullConeType(curr->type);
}
return tnhOracle->getContents(curr);
return tnhOracle->getExprContents(curr);
}

private:
Expand Down Expand Up @@ -2045,7 +2066,12 @@ Flower::Flower(Module& wasm, const PassOptions& options)
#ifdef POSSIBLE_CONTENTS_DEBUG
std::cout << "tnh phase\n";
#endif
tnhOracle = std::make_unique<TNHOracle>(wasm, options);

// Start with an empty base oracle, infer TNH once in the middle, and a
// second time.
auto base = std::make_shared<Oracle>(wasm, options);
auto mid = std::make_shared<TNHOracle>(wasm, options, base);
tnhOracle = std::make_unique<TNHOracle>(wasm, options, mid);
}

#ifdef POSSIBLE_CONTENTS_DEBUG
Expand Down
59 changes: 46 additions & 13 deletions src/ir/possible-contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,46 @@ template<> struct hash<wasm::ConeReadLocation> {

namespace wasm {

// A generic oracle, which provides an interface to query for contents at
// locations.
//
// This is not an abstract class, but can be instantiated in order to get a
// "empty" oracle, i.e., one that returns no insightful responses.
//
// A common pattern in users is to chain oracles. Each oracle can benefit from
// the inferences in the previous one before it, and it adds new inferences on
// top of that.
class Oracle {
protected:
Module& wasm;
const PassOptions& options;

public:
Oracle(Module& wasm, const PassOptions& options)
: wasm(wasm), options(options) {}

virtual ~Oracle() {}

// Get the contents possible at a location.
virtual PossibleContents getContents(Location location) const {
// Nothing useful is known in this uninsightful oracle. If we have an
// expression then we have its type, at least.
// TODO: We could also repot types of other Locations.
if (auto* exprLoc = std::get_if<ExpressionLocation>(&location)) {
return PossibleContents::fullConeType(exprLoc->expr->type);
}
return PossibleContents::many();
}

// Helper for the common case of an expression location that is not a
// multivalue.
PossibleContents getExprContents(Expression* curr) const {
assert(curr->type.size() == 1);
auto ret = getContents(ExpressionLocation{curr, 0});
return ret;
}
};

// Analyze the entire wasm file to find which contents are possible in which
// locations. This assumes a closed world and starts from roots - newly created
// values - and propagates them to the locations they reach. After the
Expand Down Expand Up @@ -632,20 +672,17 @@ namespace wasm {
// caller is assumed to know the wasm IR type anyhow, and also other
// optimization passes work on the types in the IR, so we do not focus on that
// here.
class ContentOracle {
Module& wasm;
const PassOptions& options;

class ContentOracle : public Oracle {
void analyze();

public:
ContentOracle(Module& wasm, const PassOptions& options)
: wasm(wasm), options(options) {
: Oracle(wasm, options) {
analyze();
}

// Get the contents possible at a location.
PossibleContents getContents(Location location) {
PossibleContents getContents(Location location) const override {
auto iter = locationContents.find(location);
if (iter == locationContents.end()) {
// We know of no possible contents here.
Expand All @@ -654,14 +691,10 @@ class ContentOracle {
return iter->second;
}

// Helper for the common case of an expression location that is not a
// multivalue.
PossibleContents getContents(Expression* curr) {
assert(curr->type.size() == 1);
return getContents(ExpressionLocation{curr, 0});
}

private:
// Maps locations to the content we inferred there. If a location is not
// here then no content is possible there (which is the result of the flow
// analysis not sending anything here at all).
std::unordered_map<Location, PossibleContents> locationContents;
};

Expand Down
4 changes: 2 additions & 2 deletions src/passes/GUFA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ struct GUFAOptimizer
std::unordered_map<Expression*, PossibleContents> newContents;

Expression* replaceCurrent(Expression* rep) {
newContents[rep] = oracle.getContents(getCurrent());
newContents[rep] = oracle.getExprContents(getCurrent());

return WalkerPass<
PostWalker<GUFAOptimizer,
Expand All @@ -111,7 +111,7 @@ struct GUFAOptimizer
return iter->second;
}

return oracle.getContents(curr);
return oracle.getExprContents(curr);
}

void visitExpression(Expression* curr) {
Expand Down
33 changes: 33 additions & 0 deletions test/lit/passes/gufa-tnh.wast
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,39 @@
)
)

;; An inference that requires two internal passes of the TNH oracle to achieve.
;; TODO: For this to pass, we need to not only update the oracle result for
;; the cast in $middle, but also the ref.cast itself (or read from
;; the oracle for the cast).
(module
(func $called (param $x (ref null func))
(drop
(ref.cast func
(local.get $x)
)
)
)

(func $middle (param $x (ref null func))
(call $called
(ref.cast null func
(local.get $x)
)
)
)

;; CHECK: (func $caller (type $none_=>_none)
;; CHECK-NEXT: (call $called)
;; CHECK-NEXT: )
(func $caller (param $x (ref null func)) (export "out")
(call $middle
(ref.cast null func
(local.get $x)
)
)
)
)

;; A CallRef with no non-trapping targets must be unreachable if traps never
;; happen. However, this requires closed world, so we do nothing here. (This
;; test is mirrored in gufa-tnh-closed, where closed world *is* enabled.)
Expand Down