diff options
author | Alon Zakai <azakai@google.com> | 2022-06-24 12:08:38 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-24 12:08:38 -0700 |
commit | 10523fa2468a21b0add13ccfda2d42888be72040 (patch) | |
tree | 90be1851169f313c7bc154a2597775e055b83fed /src | |
parent | 93b8849d9f98ef7ed812938ff0b3219819c2be77 (diff) | |
download | binaryen-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.cpp | 22 |
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) { |