@@ -73,14 +73,23 @@ namespace wasm {
7373// For example, if there is a switch targeting us, we can't do it - we can't remove the value from other targets
7474struct ProblemFinder : public ControlFlowWalker <ProblemFinder> {
7575 Name origin;
76- bool foundSwitch = false ;
76+ bool noWay = false ;
7777 // count br_ifs, and dropped br_ifs. if they don't match, then a br_if flow value is used, and we can't drop it
7878 Index brIfs = 0 ;
7979 Index droppedBrIfs = 0 ;
80+ PassOptions& passOptions;
81+
82+ ProblemFinder (PassOptions& passOptions) : passOptions(passOptions) {}
8083
8184 void visitBreak (Break* curr) {
82- if (curr->name == origin && curr->condition ) {
83- brIfs++;
85+ if (curr->name == origin) {
86+ if (curr->condition ) {
87+ brIfs++;
88+ }
89+ // if the value has side effects, we can't remove it
90+ if (EffectAnalyzer (passOptions, curr->value ).hasSideEffects ()) {
91+ noWay = true ;
92+ }
8493 }
8594 }
8695
@@ -94,27 +103,30 @@ struct ProblemFinder : public ControlFlowWalker<ProblemFinder> {
94103
95104 void visitSwitch (Switch* curr) {
96105 if (curr->default_ == origin) {
97- foundSwitch = true ;
106+ noWay = true ;
98107 return ;
99108 }
100109 for (auto & target : curr->targets ) {
101110 if (target == origin) {
102- foundSwitch = true ;
111+ noWay = true ;
103112 return ;
104113 }
105114 }
106115 }
107116
108117 bool found () {
109118 assert (brIfs >= droppedBrIfs);
110- return foundSwitch || brIfs > droppedBrIfs;
119+ return noWay || brIfs > droppedBrIfs;
111120 }
112121};
113122
114123// Drops values from breaks to an origin.
115124// While doing so it can create new blocks, so optimize blocks as well.
116125struct BreakValueDropper : public ControlFlowWalker <BreakValueDropper> {
117126 Name origin;
127+ PassOptions& passOptions;
128+
129+ BreakValueDropper (PassOptions& passOptions) : passOptions(passOptions) {}
118130
119131 void visitBlock (Block* curr);
120132
@@ -143,7 +155,7 @@ struct BreakValueDropper : public ControlFlowWalker<BreakValueDropper> {
143155};
144156
145157// core block optimizer routine
146- static void optimizeBlock (Block* curr, Module* module ) {
158+ static void optimizeBlock (Block* curr, Module* module , PassOptions& passOptions ) {
147159 bool more = true ;
148160 bool changed = false ;
149161 while (more) {
@@ -159,14 +171,14 @@ static void optimizeBlock(Block* curr, Module* module) {
159171 if (child->name .is ()) {
160172 Expression* expression = child;
161173 // check if it's ok to remove the value from all breaks to us
162- ProblemFinder finder;
174+ ProblemFinder finder (passOptions) ;
163175 finder.origin = child->name ;
164176 finder.walk (expression);
165177 if (finder.found ()) {
166178 child = nullptr ;
167179 } else {
168180 // fix up breaks
169- BreakValueDropper fixer;
181+ BreakValueDropper fixer (passOptions) ;
170182 fixer.origin = child->name ;
171183 fixer.setModule (module );
172184 fixer.walk (expression);
@@ -217,7 +229,7 @@ static void optimizeBlock(Block* curr, Module* module) {
217229}
218230
219231void BreakValueDropper::visitBlock (Block* curr) {
220- optimizeBlock (curr, getModule ());
232+ optimizeBlock (curr, getModule (), passOptions );
221233}
222234
223235struct MergeBlocks : public WalkerPass <PostWalker<MergeBlocks>> {
@@ -226,7 +238,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
226238 Pass* create () override { return new MergeBlocks; }
227239
228240 void visitBlock (Block *curr) {
229- optimizeBlock (curr, getModule ());
241+ optimizeBlock (curr, getModule (), getPassOptions () );
230242 }
231243
232244 Block* optimize (Expression* curr, Expression*& child, Block* outer = nullptr , Expression** dependency1 = nullptr , Expression** dependency2 = nullptr ) {
0 commit comments