diff options
-rw-r--r-- | src/ast/effects.h | 16 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_shrink-level=1.txt | 16 | ||||
-rw-r--r-- | test/passes/remove-unused-brs_shrink-level=1.wast | 16 | ||||
-rw-r--r-- | test/passes/remove-unused-names_vacuum.txt | 16 | ||||
-rw-r--r-- | test/passes/remove-unused-names_vacuum.wast | 23 |
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) + ) ) |