diff options
-rw-r--r-- | src/ir/effects.h | 52 | ||||
-rw-r--r-- | test/passes/simplify-locals.txt | 156 | ||||
-rw-r--r-- | test/passes/simplify-locals.wast | 109 |
3 files changed, 305 insertions, 12 deletions
diff --git a/src/ir/effects.h b/src/ir/effects.h index 401232fa1..1c33964a7 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -22,7 +22,7 @@ namespace wasm { // Look for side effects, including control flow // TODO: optimize -struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { +struct EffectAnalyzer : public PostWalker<EffectAnalyzer, OverriddenVisitor<EffectAnalyzer>> { EffectAnalyzer(PassOptions& passOptions, Expression *ast = nullptr) { ignoreImplicitTraps = passOptions.ignoreImplicitTraps; debugInfo = passOptions.debugInfo; @@ -149,18 +149,10 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { std::set<Name> breakNames; - void visitBreak(Break *curr) { - breakNames.insert(curr->name); - } - void visitSwitch(Switch *curr) { - for (auto name : curr->targets) { - breakNames.insert(name); - } - breakNames.insert(curr->default_); - } void visitBlock(Block* curr) { if (curr->name.is()) breakNames.erase(curr->name); // these were internal breaks } + void visitIf(If* curr) {} void visitLoop(Loop* curr) { if (curr->name.is()) breakNames.erase(curr->name); // these were internal breaks // if the loop is unreachable, then there is branching control flow: @@ -176,6 +168,15 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { branches = true; } } + void visitBreak(Break *curr) { + breakNames.insert(curr->name); + } + void visitSwitch(Switch *curr) { + for (auto name : curr->targets) { + breakNames.insert(name); + } + breakNames.insert(curr->default_); + } void visitCall(Call *curr) { calls = true; @@ -239,7 +240,31 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { isAtomic = true; if (!ignoreImplicitTraps) implicitTrap = true; }; - void visitUnary(Unary *curr) { + void visitSIMDExtract(SIMDExtract* curr) {} + void visitSIMDReplace(SIMDReplace* curr) {} + void visitSIMDShuffle(SIMDShuffle* curr) {} + void visitSIMDBitselect(SIMDBitselect* curr) {} + void visitSIMDShift(SIMDShift* curr) {} + void visitMemoryInit(MemoryInit* curr) { + writesMemory = true; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitDataDrop(DataDrop* curr) { + // prevent reordering with memory.init + readsMemory = true; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitMemoryCopy(MemoryCopy* curr) { + readsMemory = true; + writesMemory = true; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitMemoryFill(MemoryFill* curr) { + writesMemory = true; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitConst(Const* curr) {} + void visitUnary(Unary* curr) { if (!ignoreImplicitTraps) { switch (curr->op) { case TruncSFloat32ToInt32: @@ -257,7 +282,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { } } } - void visitBinary(Binary *curr) { + void visitBinary(Binary* curr) { if (!ignoreImplicitTraps) { switch (curr->op) { case DivSInt32: @@ -275,6 +300,8 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { } } } + void visitSelect(Select* curr) {} + void visitDrop(Drop* curr) {} void visitReturn(Return *curr) { branches = true; } void visitHost(Host *curr) { calls = true; @@ -283,6 +310,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { // Atomics are also sequentially consistent with grow_memory. isAtomic = true; } + void visitNop(Nop* curr) {} void visitUnreachable(Unreachable *curr) { branches = true; } // Helpers diff --git a/test/passes/simplify-locals.txt b/test/passes/simplify-locals.txt index cfb995910..7a6de1873 100644 --- a/test/passes/simplify-locals.txt +++ b/test/passes/simplify-locals.txt @@ -1720,3 +1720,159 @@ ) ) ) +(module + (type $0 (func)) + (memory $0 256 256) + (data passive "hello, there!") + (func $memory-init-load (; 0 ;) (type $0) + (local $x i32) + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (memory.init 0 + (i32.const 0) + (i32.const 0) + (i32.const 5) + ) + (drop + (local.get $x) + ) + ) + (func $memory-init-store (; 1 ;) (type $0) + (local $x i32) + (local.set $x + (block $block (result i32) + (i32.store + (i32.const 0) + (i32.const 42) + ) + (i32.const 0) + ) + ) + (memory.init 0 + (i32.const 0) + (i32.const 0) + (i32.const 5) + ) + (drop + (local.get $x) + ) + ) + (func $memory-copy-load (; 2 ;) (type $0) + (local $x i32) + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (memory.copy + (i32.const 0) + (i32.const 8) + (i32.const 8) + ) + (drop + (local.get $x) + ) + ) + (func $memory-copy-store (; 3 ;) (type $0) + (local $x i32) + (local.set $x + (block $block (result i32) + (i32.store + (i32.const 0) + (i32.const 42) + ) + (i32.const 0) + ) + ) + (memory.copy + (i32.const 0) + (i32.const 8) + (i32.const 8) + ) + (drop + (local.get $x) + ) + ) + (func $memory-fill-load (; 4 ;) (type $0) + (local $x i32) + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (memory.fill + (i32.const 0) + (i32.const 42) + (i32.const 8) + ) + (drop + (local.get $x) + ) + ) + (func $memory-fill-store (; 5 ;) (type $0) + (local $x i32) + (local.set $x + (block $block (result i32) + (i32.store + (i32.const 0) + (i32.const 42) + ) + (i32.const 0) + ) + ) + (memory.fill + (i32.const 0) + (i32.const 8) + (i32.const 8) + ) + (drop + (local.get $x) + ) + ) + (func $data-drop-load (; 6 ;) (type $0) + (local $x i32) + (nop) + (data.drop 0) + (drop + (i32.load + (i32.const 0) + ) + ) + ) + (func $data-drop-store (; 7 ;) (type $0) + (local $x i32) + (local.set $x + (block $block (result i32) + (i32.store + (i32.const 0) + (i32.const 42) + ) + (i32.const 0) + ) + ) + (data.drop 0) + (drop + (local.get $x) + ) + ) + (func $data-drop-memory-init (; 8 ;) (type $0) + (local $x i32) + (local.set $x + (block $block (result i32) + (memory.init 0 + (i32.const 0) + (i32.const 0) + (i32.const 5) + ) + (i32.const 0) + ) + ) + (data.drop 0) + (drop + (local.get $x) + ) + ) +) diff --git a/test/passes/simplify-locals.wast b/test/passes/simplify-locals.wast index 1f25f5427..34a93d442 100644 --- a/test/passes/simplify-locals.wast +++ b/test/passes/simplify-locals.wast @@ -1546,3 +1546,112 @@ (call $tee-chain (local.get $x) (local.get $z) (local.get $t1) (local.get $t2) (local.get $t3)) ) ) +(module + (memory 256 256) + (data passive "hello, there!") + (func $memory-init-load + (local $x i32) + (local.set $x + (i32.load (i32.const 0)) + ) + (memory.init 0 (i32.const 0) (i32.const 0) (i32.const 5)) + (drop + (local.get $x) + ) + ) + (func $memory-init-store + (local $x i32) + (local.set $x + (block i32 + (i32.store (i32.const 0) (i32.const 42)) + (i32.const 0) + ) + ) + (memory.init 0 (i32.const 0) (i32.const 0) (i32.const 5)) + (drop + (local.get $x) + ) + ) + (func $memory-copy-load + (local $x i32) + (local.set $x + (i32.load (i32.const 0)) + ) + (memory.copy (i32.const 0) (i32.const 8) (i32.const 8)) + (drop + (local.get $x) + ) + ) + (func $memory-copy-store + (local $x i32) + (local.set $x + (block i32 + (i32.store (i32.const 0) (i32.const 42)) + (i32.const 0) + ) + ) + (memory.copy (i32.const 0) (i32.const 8) (i32.const 8)) + (drop + (local.get $x) + ) + ) + (func $memory-fill-load + (local $x i32) + (local.set $x + (i32.load (i32.const 0)) + ) + (memory.fill (i32.const 0) (i32.const 42) (i32.const 8)) + (drop + (local.get $x) + ) + ) + (func $memory-fill-store + (local $x i32) + (local.set $x + (block i32 + (i32.store (i32.const 0) (i32.const 42)) + (i32.const 0) + ) + ) + (memory.fill (i32.const 0) (i32.const 8) (i32.const 8)) + (drop + (local.get $x) + ) + ) + (func $data-drop-load + (local $x i32) + (local.set $x + (i32.load (i32.const 0)) + ) + (data.drop 0) + (drop + (local.get $x) + ) + ) + (func $data-drop-store + (local $x i32) + (local.set $x + (block i32 + (i32.store (i32.const 0) (i32.const 42)) + (i32.const 0) + ) + ) + (data.drop 0) + (drop + (local.get $x) + ) + ) + (func $data-drop-memory-init + (local $x i32) + (local.set $x + (block i32 + (memory.init 0 (i32.const 0) (i32.const 0) (i32.const 5)) + (i32.const 0) + ) + ) + (data.drop 0) + (drop + (local.get $x) + ) + ) +) |