diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index fff18b925..64d59ca1d 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2248,8 +2248,27 @@ struct OptimizeInstructions } if (curr->op == ExternConvertAny || curr->op == AnyConvertExtern) { - // We can't optimize these. Even removing a non-null cast is not valid as - // they allow nulls to filter through, unlike other RefAs*. + // These pass nulls through, and we can reorder them with null traps: + // + // (any.convert_extern/extern.convert_any (ref.as_non_null.. )) + // => + // (ref.as_non_null (any.convert_extern/extern.convert_any ..)) + // + // By moving the RefAsNonNull outside, it may reach a position where it + // can be optimized (e.g. if the parent traps anyhow). And, + // ExternConvertAny/AnyConvertExtern cannot be folded with anything, so + // there is no harm to moving them inside. + if (auto* refAsChild = curr->value->dynCast<RefAs>()) { + if (refAsChild->op == RefAsNonNull) { + // Reorder and fix up the types. + curr->value = refAsChild->value; + curr->finalize(); + refAsChild->value = curr; + refAsChild->finalize(); + replaceCurrent(refAsChild); + } + } + // TODO: optimize away ExternConvertAny of AnyConvertExtern, etc. return; } |