Skip to content

Commit a4dd239

Browse files
authored
JIT: Disable recursive tailcall to loop opt in OSR methods (#113625)
OSR is meant to be used when we can't escape, but these tailcalls are natural points where we're actually able to escape. So prefer call counting + tiering + potential transition into the tier 1 code in these situations.
1 parent 295338c commit a4dd239

File tree

1 file changed

+12
-18
lines changed

1 file changed

+12
-18
lines changed

src/coreclr/jit/morph.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4686,8 +4686,13 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call)
46864686
// fgMorphRecursiveFastTailCallIntoLoop() is not handling update of generic context while transforming
46874687
// a recursive call into a loop. Another option is to modify gtIsRecursiveCall() to check that the
46884688
// generic type parameters of both caller and callee generic method are the same.
4689-
if (opts.compTailCallLoopOpt && canFastTailCall && gtIsRecursiveCall(call) && !lvaReportParamTypeArg() &&
4690-
!lvaKeepAliveAndReportThis() && !call->IsVirtual() && !hasStructParam && !varTypeIsStruct(call->TypeGet()))
4689+
//
4690+
// For OSR, we prefer to tailcall for call counting + potential transition
4691+
// into the actual tier1 version.
4692+
//
4693+
if (opts.compTailCallLoopOpt && canFastTailCall && !opts.IsOSR() && gtIsRecursiveCall(call) &&
4694+
!lvaReportParamTypeArg() && !lvaKeepAliveAndReportThis() && !call->IsVirtual() && !hasStructParam &&
4695+
!varTypeIsStruct(call->TypeGet()))
46914696
{
46924697
fastTailCallToLoop = true;
46934698
}
@@ -6161,23 +6166,12 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa
61616166
// Remove the call
61626167
fgRemoveStmt(block, lastStmt);
61636168

6169+
assert(!opts.IsOSR());
61646170
// Set the loop edge.
6165-
BasicBlock* entryBB;
6166-
if (opts.IsOSR())
6167-
{
6168-
// Todo: this may not look like a viable loop header.
6169-
// Might need the moral equivalent of an init BB.
6170-
entryBB = fgEntryBB;
6171-
}
6172-
else
6173-
{
6174-
assert(doesMethodHaveRecursiveTailcall());
6175-
6176-
// TODO-Cleanup: We should really be expanding tailcalls into loops
6177-
// much earlier than this, at a place where we do not need to have
6178-
// hacky workarounds to figure out what the actual IL entry block is.
6179-
entryBB = fgGetFirstILBlock();
6180-
}
6171+
// TODO-Cleanup: We should really be expanding tailcalls into loops much
6172+
// earlier than this, at a place where we can just use the init BB here.
6173+
BasicBlock* entryBB = fgGetFirstILBlock();
6174+
assert(doesMethodHaveRecursiveTailcall());
61816175

61826176
FlowEdge* const newEdge = fgAddRefPred(entryBB, block);
61836177
block->SetKindAndTargetEdge(BBJ_ALWAYS, newEdge);

0 commit comments

Comments
 (0)