diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2019-07-19 16:24:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-19 16:24:37 -0700 |
commit | 72c52ea7d4eb61b95cf8a5164947cb760fe42e9c (patch) | |
tree | 137998155be428183fb09da95e9d0d0707efa4bc /src/passes/MemoryPacking.cpp | |
parent | 88ef839433ac0cf58c2a29f369d0268a22b5ae0e (diff) | |
download | binaryen-72c52ea7d4eb61b95cf8a5164947cb760fe42e9c.tar.gz binaryen-72c52ea7d4eb61b95cf8a5164947cb760fe42e9c.tar.bz2 binaryen-72c52ea7d4eb61b95cf8a5164947cb760fe42e9c.zip |
Remove bulk memory instructions refering to active segments (#2235)
This prevents those instructions from becoming invalid due to memory
packing optimizations and is also a code size win. Fixes #2227.
Diffstat (limited to 'src/passes/MemoryPacking.cpp')
-rw-r--r-- | src/passes/MemoryPacking.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp index 0b24379e5..f98c25096 100644 --- a/src/passes/MemoryPacking.cpp +++ b/src/passes/MemoryPacking.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "ir/manipulation.h" +#include "ir/utils.h" #include "pass.h" #include "wasm-binary.h" #include "wasm-builder.h" @@ -32,11 +34,13 @@ struct MemoryPacking : public Pass { return; } - // Conservatively refuse to change segments if any are passive to avoid - // invalidating segment indices or segment contents referenced from - // memory.init instructions. - // TODO: optimize in the presence of memory.init instructions if (module->features.hasBulkMemory()) { + // Remove any references to active segments that might be invalidated. + optimizeTrappingBulkMemoryOps(runner, module); + // Conservatively refuse to change segments if any are passive to avoid + // invalidating segment indices or segment contents referenced from + // memory.init and data.drop instructions. + // TODO: optimize in the presence of memory.init and data.drop for (auto segment : module->memory.segments) { if (segment.isPassive) { return; @@ -120,6 +124,38 @@ struct MemoryPacking : public Pass { } module->memory.segments.swap(packed); } + + void optimizeTrappingBulkMemoryOps(PassRunner* runner, Module* module) { + struct Trapper : WalkerPass<PostWalker<Trapper>> { + bool changed; + void visitMemoryInit(MemoryInit* curr) { + if (!getModule()->memory.segments[curr->segment].isPassive) { + Builder builder(*getModule()); + replaceCurrent(builder.blockify(builder.makeDrop(curr->dest), + builder.makeDrop(curr->offset), + builder.makeDrop(curr->size), + builder.makeUnreachable())); + changed = true; + } + } + void visitDataDrop(DataDrop* curr) { + if (!getModule()->memory.segments[curr->segment].isPassive) { + ExpressionManipulator::unreachable(curr); + changed = true; + } + } + void walkFunction(Function* func) { + changed = false; + PostWalker<Trapper>::walkFunction(func); + if (changed) { + ReFinalize().walkFunctionInModule(func, getModule()); + } + } + bool isFunctionParallel() override { return true; } + Pass* create() override { return new Trapper; } + } trapper; + trapper.run(runner, module); + } }; Pass* createMemoryPackingPass() { return new MemoryPacking(); } |