diff options
Diffstat (limited to 'src/passes/Inlining.cpp')
-rw-r--r-- | src/passes/Inlining.cpp | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 36610a224..21c06e528 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -247,6 +247,7 @@ struct Updater : public PostWalker<Updater> { Module* module; std::map<Index, Index> localMapping; Name returnName; + bool isReturn; Builder* builder; void visitReturn(Return* curr) { replaceCurrent(builder->makeBreak(returnName, curr->value)); @@ -257,6 +258,14 @@ struct Updater : public PostWalker<Updater> { // not cause unbounded stack growth because inlining and return calling both // avoid creating a new stack frame. template<typename T> void handleReturnCall(T* curr, HeapType targetType) { + if (isReturn) { + // If the inlined callsite was already a return_call, then we can keep + // return_calls in the inlined function rather than downgrading them. + // That is, if A->B and B->C and both those calls are return_calls + // then after inlining A->B we want to now have A->C be a + // return_call. + return; + } curr->isReturn = false; curr->type = targetType.getSignature().results; if (curr->type.isConcrete()) { @@ -329,6 +338,7 @@ doInlining(Module* module, Function* into, const InliningAction& action) { Updater updater; updater.module = module; updater.returnName = block->name; + updater.isReturn = call->isReturn; updater.builder = &builder; // Set up a locals mapping for (Index i = 0; i < from->getNumLocals(); i++) { |