diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/Inlining.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 30bb5c23f..cbee7e77f 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -446,11 +446,11 @@ struct Updater : public TryDepthWalker<Updater> { }; // Core inlining logic. Modifies the outside function (adding locals as -// needed). -static void doInlining(Module* module, - Function* into, - const InliningAction& action, - PassOptions& options) { +// needed) by copying the inlined code into it. +static void doCodeInlining(Module* module, + Function* into, + const InliningAction& action, + PassOptions& options) { Function* from = action.contents; auto* call = (*action.callSite)->cast<Call>(); @@ -622,6 +622,12 @@ static void doInlining(Module* module, } *action.callSite = builder.makeSequence(old, builder.makeUnreachable()); } +} + +// Updates the outer function after we inline into it. This is a general +// operation that does not depend on what we inlined, it just makes sure that we +// refinalize everything, have no duplicate break labels, etc. +static void updateAfterInlining(Module* module, Function* into) { // Anything we inlined into may now have non-unique label names, fix it up. // Note that we must do this before refinalization, as otherwise duplicate // block labels can lead to errors (the IR must be valid before we @@ -635,6 +641,14 @@ static void doInlining(Module* module, TypeUpdating::handleNonDefaultableLocals(into, *module); } +static void doInlining(Module* module, + Function* into, + const InliningAction& action, + PassOptions& options) { + doCodeInlining(module, into, action, options); + updateAfterInlining(module, into); +} + // A map of function names to the inlining actions we've decided to actually // perform in them. using ChosenActions = std::unordered_map<Name, std::vector<InliningAction>>; @@ -657,9 +671,13 @@ struct DoInlining : public Pass { assert(iter != chosenActions.end()); const auto& actions = iter->second; assert(!actions.empty()); + + // Inline all the code first, then update func once at the end (which saves + // e.g. running ReFinalize after each action, of which there might be many). for (auto action : actions) { - doInlining(module, func, action, getPassOptions()); + doCodeInlining(module, func, action, getPassOptions()); } + updateAfterInlining(module, func); } private: |