@@ -29,14 +29,7 @@ namespace wasm {
2929
3030namespace {
3131
32- constexpr auto UnknownEffects = std::nullopt ;
33-
3432struct FuncInfo {
35- // Effects in this function. nullopt / UnknownEffects means that we don't know
36- // what effects this function has, so we conservatively assume all effects.
37- // Nullopt cases won't be copied to Function::effects.
38- std::optional<EffectAnalyzer> effects;
39-
4033 // Directly-called functions from this function.
4134 std::unordered_set<Name> calledFunctions;
4235};
@@ -46,37 +39,39 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
4639 ModuleUtils::ParallelFunctionAnalysis<FuncInfo> analysis (
4740 module , [&](Function* func, FuncInfo& funcInfo) {
4841 if (func->imported ()) {
49- // Imports can do anything, so we need to assume the worst anyhow,
50- // which is the same as not specifying any effects for them in the
51- // map (which we do by not setting funcInfo.effects).
42+ // Imports can do anything, so we need to assume the worst anyhow.
43+ func->effects = nullptr ;
5244 return ;
5345 }
5446
5547 // Gather the effects.
56- funcInfo.effects .emplace (passOptions, module , func);
48+ func->effects =
49+ std::make_shared<EffectAnalyzer>(passOptions, module , func);
5750
58- if (funcInfo. effects ->calls ) {
51+ if (func-> effects ->calls ) {
5952 // There are calls in this function, which we will analyze in detail.
6053 // Clear the |calls| field first, and we'll handle calls of all sorts
6154 // below.
62- funcInfo. effects ->calls = false ;
55+ func-> effects ->calls = false ;
6356
6457 // Clear throws as well, as we are "forgetting" calls right now, and
6558 // want to forget their throwing effect as well. If we see something
6659 // else that throws, below, then we'll note that there.
67- funcInfo. effects ->throws_ = false ;
60+ func-> effects ->throws_ = false ;
6861
6962 struct CallScanner
7063 : public PostWalker<CallScanner,
7164 UnifiedExpressionVisitor<CallScanner>> {
7265 Module& wasm;
7366 const PassOptions& options;
7467 FuncInfo& funcInfo;
68+ Function* func;
7569
7670 CallScanner (Module& wasm,
7771 const PassOptions& options,
78- FuncInfo& funcInfo)
79- : wasm(wasm), options(options), funcInfo(funcInfo) {}
72+ FuncInfo& funcInfo,
73+ Function* func)
74+ : wasm(wasm), options(options), funcInfo(funcInfo), func(func) {}
8075
8176 void visitExpression (Expression* curr) {
8277 ShallowEffectAnalyzer effects (options, wasm, curr);
@@ -88,18 +83,18 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
8883 // worst. To do so, clear the effects, which indicates nothing
8984 // is known (so anything is possible).
9085 // TODO: We could group effects by function type etc.
91- funcInfo. effects = UnknownEffects ;
86+ func-> effects = nullptr ;
9287 } else {
9388 // No call here, but update throwing if we see it. (Only do so,
9489 // however, if we have effects; if we cleared it - see before -
9590 // then we assume the worst anyhow, and have nothing to update.)
96- if (effects.throws_ && funcInfo. effects ) {
97- funcInfo. effects ->throws_ = true ;
91+ if (effects.throws_ && func-> effects ) {
92+ func-> effects ->throws_ = true ;
9893 }
9994 }
10095 }
10196 };
102- CallScanner scanner (module , passOptions, funcInfo);
97+ CallScanner scanner (module , passOptions, funcInfo, func );
10398 scanner.walkFunction (func);
10499 }
105100 });
@@ -171,15 +166,15 @@ void propagateEffects(
171166 CallGraphSCCs sccs (allFuncs, funcInfos, callGraph, module );
172167
173168 std::unordered_map<Function*, int > sccMembers;
174- std::unordered_map<int , std::optional <EffectAnalyzer>> componentEffects;
169+ std::unordered_map<int , std::shared_ptr <EffectAnalyzer>> componentEffects;
175170
176171 int ccIndex = 0 ;
177172 for (auto ccIterator : sccs) {
178173 ccIndex++;
179- std::optional <EffectAnalyzer>& ccEffects = componentEffects[ccIndex];
174+ std::shared_ptr <EffectAnalyzer>& ccEffects = componentEffects[ccIndex];
180175 std::vector<Function*> ccFuncs (ccIterator.begin (), ccIterator.end ());
181176
182- ccEffects. emplace (passOptions, module );
177+ ccEffects = std::make_shared<EffectAnalyzer> (passOptions, module );
183178
184179 for (Function* f : ccFuncs) {
185180 sccMembers.emplace (f, ccIndex);
@@ -199,25 +194,25 @@ void propagateEffects(
199194 // Merge in effects from callees
200195 for (int calleeScc : calleeSccs) {
201196 const auto & calleeComponentEffects = componentEffects.at (calleeScc);
202- if (calleeComponentEffects == UnknownEffects ) {
203- ccEffects = UnknownEffects ;
197+ if (calleeComponentEffects == nullptr ) {
198+ ccEffects = nullptr ;
204199 break ;
205200 }
206201
207- else if (ccEffects != UnknownEffects ) {
202+ else if (ccEffects != nullptr ) {
208203 ccEffects->mergeIn (*calleeComponentEffects);
209204 }
210205 }
211206
212207 // Add trap effects for potential cycles.
213208 if (ccFuncs.size () > 1 ) {
214- if (ccEffects != UnknownEffects ) {
209+ if (ccEffects != nullptr ) {
215210 ccEffects->trap = true ;
216211 }
217212 } else {
218213 auto * func = ccFuncs[0 ];
219214 if (funcInfos.at (func).calledFunctions .contains (func->name )) {
220- if (ccEffects != UnknownEffects ) {
215+ if (ccEffects != nullptr ) {
221216 ccEffects->trap = true ;
222217 }
223218 }
@@ -226,9 +221,9 @@ void propagateEffects(
226221 // Aggregate effects within this CC
227222 if (ccEffects) {
228223 for (Function* f : ccFuncs) {
229- const auto & effects = funcInfos. at (f). effects ;
230- if (effects == UnknownEffects ) {
231- ccEffects = UnknownEffects ;
224+ const auto & effects = f-> effects ;
225+ if (effects == nullptr ) {
226+ ccEffects = nullptr ;
232227 break ;
233228 }
234229
@@ -238,23 +233,8 @@ void propagateEffects(
238233
239234 // Assign each function's effects to its CC effects.
240235 for (Function* f : ccFuncs) {
241- if (!ccEffects) {
242- funcInfos.at (f).effects = UnknownEffects;
243- } else {
244- funcInfos.at (f).effects .emplace (*ccEffects);
245- }
246- }
247- }
248- }
249-
250- void copyEffectsToFunctions (const std::map<Function*, FuncInfo> funcInfos) {
251- for (auto & [func, info] : funcInfos) {
252- func->effects .reset ();
253- if (!info.effects ) {
254- continue ;
236+ f->effects = ccEffects;
255237 }
256-
257- func->effects = std::make_shared<EffectAnalyzer>(*info.effects );
258238 }
259239}
260240
@@ -266,8 +246,6 @@ struct GenerateGlobalEffects : public Pass {
266246 auto callGraph = buildCallGraph (*module , funcInfos);
267247
268248 propagateEffects (*module , getPassOptions (), funcInfos, callGraph);
269-
270- copyEffectsToFunctions (funcInfos);
271249 }
272250};
273251
0 commit comments