summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-06-24 12:08:38 -0700
committerGitHub <noreply@github.com>2022-06-24 12:08:38 -0700
commit10523fa2468a21b0add13ccfda2d42888be72040 (patch)
tree90be1851169f313c7bc154a2597775e055b83fed /src
parent93b8849d9f98ef7ed812938ff0b3219819c2be77 (diff)
downloadbinaryen-10523fa2468a21b0add13ccfda2d42888be72040.tar.gz
binaryen-10523fa2468a21b0add13ccfda2d42888be72040.tar.bz2
binaryen-10523fa2468a21b0add13ccfda2d42888be72040.zip
[WasmGC] OptimizeInstructions: Improve RefIs cast ordering (#4752)
#4748 regressed us in some cases, because it removed casts first: (ref.is_func (ref.as_func (local.get $anyref))) If the cast is removed first, and the local has no useful type info, then we'd have removed the cast but could not remove the ref.is. But the ref.is could be optimized to 1, as it must be a func - the type info proves it thanks to the cast. To avoid this, remove casts after everything else.
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index ebe551d0c..f2ca4e0be 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1853,10 +1853,6 @@ struct OptimizeInstructions
return;
}
- // What the reference points to does not depend on the type, so casts may be
- // removable.
- skipCast(curr->value);
-
// Optimizating RefIs is not that obvious, since even if we know the result
// evaluates to 0 or 1 then the replacement may not actually save code size,
// since RefIsNull is a single byte (the others are 2), while adding a Const
@@ -1874,6 +1870,21 @@ struct OptimizeInstructions
replaceCurrent(builder.makeSequence(
builder.makeDrop(curr->value),
builder.makeConst(Literal::makeZero(Type::i32))));
+ } else {
+ // What the reference points to does not depend on the type, so casts
+ // may be removable. Do this right before returning because removing a
+ // cast may remove info that we could have used to optimize. For
+ // example:
+ //
+ // (ref.is_func
+ // (ref.as_func
+ // (local.get $anyref)))
+ //
+ // The local has no useful type info. The cast forces it to be a
+ // function, so we can replace the ref.is with 1. But if we removed the
+ // ref.as first then we'd not have the type info we need to optimize
+ // that way.
+ skipCast(curr->value);
}
return;
}
@@ -1913,6 +1924,9 @@ struct OptimizeInstructions
}
}
}
+
+ // See above comment.
+ skipCast(curr->value);
}
void visitRefAs(RefAs* curr) {