summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/effects.h16
-rw-r--r--test/passes/remove-unused-brs_shrink-level=1.txt16
-rw-r--r--test/passes/remove-unused-brs_shrink-level=1.wast16
-rw-r--r--test/passes/remove-unused-names_vacuum.txt16
-rw-r--r--test/passes/remove-unused-names_vacuum.wast23
5 files changed, 79 insertions, 8 deletions
diff --git a/src/ast/effects.h b/src/ast/effects.h
index a7a5d8fb2..6e4bb617e 100644
--- a/src/ast/effects.h
+++ b/src/ast/effects.h
@@ -39,7 +39,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
if (breakNames.size() > 0) branches = true;
}
- bool branches = false; // branches out of this expression
+ bool branches = false; // branches out of this expression, returns, infinite loops, etc
bool calls = false;
std::set<Index> localsRead;
std::set<Index> localsWritten;
@@ -138,6 +138,18 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
}
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:
+ // (1) if the body is unreachable because of a (return), uncaught (br) etc., then we
+ // already noted branching, so it is ok to mark it again (if we have *caught*
+ // (br)s, then they did not lead to the loop body being unreachable).
+ // (same logic applies to blocks)
+ // (2) if the loop is unreachable because it only has branches up to the loop
+ // top, but no way to get out, then it is an infinite loop, and we consider
+ // that a branching side effect (note how the same logic does not apply to
+ // blocks).
+ if (curr->type == unreachable) {
+ branches = true;
+ }
}
void visitCall(Call *curr) { calls = true; }
@@ -182,6 +194,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
case TruncUFloat64ToInt32:
case TruncUFloat64ToInt64: {
implicitTrap = true;
+ break;
}
default: {}
}
@@ -199,6 +212,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
case RemSInt64:
case RemUInt64: {
implicitTrap = true;
+ break;
}
default: {}
}
diff --git a/test/passes/remove-unused-brs_shrink-level=1.txt b/test/passes/remove-unused-brs_shrink-level=1.txt
index 09e727ea5..a26f4ebf4 100644
--- a/test/passes/remove-unused-brs_shrink-level=1.txt
+++ b/test/passes/remove-unused-brs_shrink-level=1.txt
@@ -123,4 +123,20 @@
)
)
)
+ (func $join-and-it-becomes-unreachable (type $1)
+ (block $label$1
+ (block $block
+ (br_if $label$1
+ (i32.load8_u
+ (i32.const -93487262)
+ )
+ )
+ (br_if $label$1
+ (loop $label$5
+ (br $label$5)
+ )
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/remove-unused-brs_shrink-level=1.wast b/test/passes/remove-unused-brs_shrink-level=1.wast
index 000658b91..88977be9e 100644
--- a/test/passes/remove-unused-brs_shrink-level=1.wast
+++ b/test/passes/remove-unused-brs_shrink-level=1.wast
@@ -77,5 +77,21 @@
(br_if $out8 (call $b14)) ;; side effect
)
)
+ (func $join-and-it-becomes-unreachable
+ (block $label$1
+ (block
+ (br_if $label$1
+ (i32.load8_u
+ (i32.const -93487262)
+ )
+ )
+ (br_if $label$1
+ (loop $label$5 ;; this is unreachable (infinite loop, no exit)
+ (br $label$5)
+ )
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/remove-unused-names_vacuum.txt b/test/passes/remove-unused-names_vacuum.txt
index 999d8915e..d27fb3d65 100644
--- a/test/passes/remove-unused-names_vacuum.txt
+++ b/test/passes/remove-unused-names_vacuum.txt
@@ -4,11 +4,15 @@
(memory $0 0)
(func $return-i32-but-body-is-unreachable3 (type $0) (result i32)
(local $label i32)
- (unreachable)
+ (loop $while-in$1
+ (br $while-in$1)
+ )
)
(func $return-i32-but-body-is-unreachable4 (type $0) (result i32)
(local $label i32)
- (unreachable)
+ (loop $while-in$1
+ (br $while-in$1)
+ )
)
(func $to-drop-unreachable (type $1)
(drop
@@ -17,4 +21,12 @@
)
)
)
+ (func $return-i32-but-body-is-unreachable5 (type $0) (result i32)
+ (local $label i32)
+ (unreachable)
+ )
+ (func $return-i32-but-body-is-unreachable6 (type $0) (result i32)
+ (local $label i32)
+ (unreachable)
+ )
)
diff --git a/test/passes/remove-unused-names_vacuum.wast b/test/passes/remove-unused-names_vacuum.wast
index f45f50274..66412353c 100644
--- a/test/passes/remove-unused-names_vacuum.wast
+++ b/test/passes/remove-unused-names_vacuum.wast
@@ -16,12 +16,25 @@
)
(i32.const 0)
)
- (func $to-drop-unreachable
- (drop
- (block (result i32)
- (unreachable)
+ (func $to-drop-unreachable
+ (drop
+ (block (result i32)
+ (unreachable)
+ )
)
)
- )
+ (func $return-i32-but-body-is-unreachable5 (result i32)
+ (local $label i32)
+ (block ;; without a name here, vaccum had a too-eager bug
+ (unreachable)
+ )
+ )
+ (func $return-i32-but-body-is-unreachable6 (result i32)
+ (local $label i32)
+ (block ;; without a name here, vaccum had a too-eager bug
+ (unreachable)
+ )
+ (i32.const 0)
+ )
)