@@ -1561,7 +1561,6 @@ void TranslateToFuzzReader::modFunction(Function* func) {
15611561 // still want to run them some of the time, at least, so that we
15621562 // check variations on initial testcases even at the risk of OOB.
15631563 recombine (func);
1564- fixAfterChanges (func);
15651564 mutate (func);
15661565 fixAfterChanges (func);
15671566}
@@ -1735,6 +1734,9 @@ void TranslateToFuzzReader::mutate(Function* func) {
17351734 // reasonable chance of making some changes.
17361735 percentChance = std::max (percentChance, Index (3 ));
17371736
1737+ // Half the time, use the SubtypingDiscoverer below.
1738+ bool useSubtypingDiscoverer = r & 1 ;
1739+
17381740 // First, find things to replace and their types. SubtypingDiscoverer needs to
17391741 // do this in a single, full walk (as types of children depend on parents, and
17401742 // even block targets).
@@ -1771,7 +1773,17 @@ void TranslateToFuzzReader::mutate(Function* func) {
17711773 void noteCast (Expression* src, Type dst) {}
17721774 void noteCast (Expression* src, Expression* dst) {}
17731775 } finder;
1774- finder.walkFunctionInModule (func, &wasm);
1776+
1777+ if (useSubtypingDiscoverer) {
1778+ // We read the IR here, and it must be totally valid - e.g. breaks have a
1779+ // proper break target - or else we'd hit internal errors. Fix it up first.
1780+ // (Otherwise, fixing it up is done once after mutation, and in that case
1781+ // we can mutate the IR in simple ways but not read it using
1782+ // useSubtypingDiscoverer). We avoid always doing this second fixup as it
1783+ // may bias the code in some ways.
1784+ fixAfterChanges (func);
1785+ finder.walkFunctionInModule (func, &wasm);
1786+ }
17751787
17761788 // Next, modify things.
17771789 struct Modder : public PostWalker <Modder, UnifiedExpressionVisitor<Modder>> {
0 commit comments