@@ -39,7 +39,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
3939 if (breakNames.size () > 0 ) branches = true ;
4040 }
4141
42- bool branches = false ; // branches out of this expression
42+ bool branches = false ; // branches out of this expression, returns, infinite loops, etc
4343 bool calls = false ;
4444 std::set<Index> localsRead;
4545 std::set<Index> localsWritten;
@@ -138,6 +138,18 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
138138 }
139139 void visitLoop (Loop* curr) {
140140 if (curr->name .is ()) breakNames.erase (curr->name ); // these were internal breaks
141+ // if the loop is unreachable, then there is branching control flow:
142+ // (1) if the body is unreachable because of a (return), uncaught (br) etc., then we
143+ // already noted branching, so it is ok to mark it again (if we have *caught*
144+ // (br)s, then they did not lead to the loop body being unreachable).
145+ // (same logic applies to blocks)
146+ // (2) if the loop is unreachable because it only has branches up to the loop
147+ // top, but no way to get out, then it is an infinite loop, and we consider
148+ // that a branching side effect (note how the same logic does not apply to
149+ // blocks).
150+ if (curr->type == unreachable) {
151+ branches = true ;
152+ }
141153 }
142154
143155 void visitCall (Call *curr) { calls = true ; }
@@ -182,6 +194,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
182194 case TruncUFloat64ToInt32:
183195 case TruncUFloat64ToInt64: {
184196 implicitTrap = true ;
197+ break ;
185198 }
186199 default : {}
187200 }
@@ -199,6 +212,7 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> {
199212 case RemSInt64:
200213 case RemUInt64: {
201214 implicitTrap = true ;
215+ break ;
202216 }
203217 default : {}
204218 }
0 commit comments