summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/effects.h52
-rw-r--r--test/passes/simplify-locals.txt156
-rw-r--r--test/passes/simplify-locals.wast109
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)
+ )
+ )
+)