summaryrefslogtreecommitdiff
path: root/src/passes/GUFA.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/GUFA.cpp')
-rw-r--r--src/passes/GUFA.cpp29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/passes/GUFA.cpp b/src/passes/GUFA.cpp
index 53693420e..1f620f8db 100644
--- a/src/passes/GUFA.cpp
+++ b/src/passes/GUFA.cpp
@@ -233,6 +233,35 @@ struct GUFAOptimizer
}
}
+ void visitRefTest(RefTest* curr) {
+ if (curr->type == Type::unreachable) {
+ // Leave this for DCE.
+ return;
+ }
+
+ auto refContents = getContents(curr->ref);
+ auto refType = refContents.getType();
+ if (refType.isRef()) {
+ // We have some knowledge of the type here. Use that to optimize: RefTest
+ // returns 1 iff the input is not null and is also a subtype.
+ bool isSubType =
+ HeapType::isSubType(refType.getHeapType(), curr->intendedType);
+ bool mayBeNull = refType.isNullable();
+
+ auto optimize = [&](int32_t result) {
+ auto* last = Builder(*getModule()).makeConst(Literal(int32_t(result)));
+ replaceCurrent(getDroppedChildrenAndAppend(
+ curr, *getModule(), getPassOptions(), last));
+ };
+
+ if (!isSubType) {
+ optimize(0);
+ } else if (!mayBeNull) {
+ optimize(1);
+ }
+ }
+ }
+
// TODO: If an instruction would trap on null, like struct.get, we could
// remove it here if it has no possible contents and if we are in
// traps-never-happen mode (that is, we'd have proven it can only trap,