Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1901,17 +1901,16 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
codeGen = nullptr;
}

compJmpOpUsed = false;
compLongUsed = false;
compTailCallUsed = false;
compTailPrefixSeen = false;
compMayConvertTailCallToLoop = false;
compLocallocSeen = false;
compLocallocUsed = false;
compLocallocOptimized = false;
compQmarkRationalized = false;
compQmarkUsed = false;
compFloatingPointUsed = false;
compJmpOpUsed = false;
compLongUsed = false;
compTailCallUsed = false;
compTailPrefixSeen = false;
compLocallocSeen = false;
compLocallocUsed = false;
compLocallocOptimized = false;
compQmarkRationalized = false;
compQmarkUsed = false;
compFloatingPointUsed = false;

compSuppressedZeroInit = false;

Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7118,6 +7118,7 @@ class Compiler
#define OMF_HAS_STATIC_INIT 0x00008000 // Method has static initializations we might want to partially inline
#define OMF_HAS_TLS_FIELD 0x00010000 // Method contains TLS field access
#define OMF_HAS_SPECIAL_INTRINSICS 0x00020000 // Method contains special intrinsics expanded in late phases
#define OMF_HAS_RECURSIVE_TAILCALL 0x00040000 // Method contains recursive tail call

// clang-format on

Expand Down Expand Up @@ -7188,6 +7189,16 @@ class Compiler
optMethodFlags |= OMF_HAS_SPECIAL_INTRINSICS;
}

bool doesMethodHaveRecursiveTailcall()
{
return (optMethodFlags & OMF_HAS_RECURSIVE_TAILCALL) != 0;
}

void setMethodHasRecursiveTailcall()
{
optMethodFlags |= OMF_HAS_RECURSIVE_TAILCALL;
}

void pickGDV(GenTreeCall* call,
IL_OFFSET ilOffset,
bool isInterface,
Expand Down Expand Up @@ -9361,7 +9372,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
bool compFloatingPointUsed; // Does the method use TYP_FLOAT or TYP_DOUBLE
bool compTailCallUsed; // Does the method do a tailcall
bool compTailPrefixSeen; // Does the method IL have tail. prefix
bool compMayConvertTailCallToLoop; // Does the method have a recursive tail call that we may convert to a loop?
bool compLocallocSeen; // Does the method IL have localloc opcode
bool compLocallocUsed; // Does the method use localloc.
bool compLocallocOptimized; // Does the method have an optimized localloc
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
dspTreeID(call), loopHead->bbNum, compCurBB->bbNum);
fgMarkBackwardJump(loopHead, compCurBB);

compMayConvertTailCallToLoop = true;
setMethodHasRecursiveTailcall();
compCurBB->bbFlags |= BBF_RECURSIVE_TAILCALL;
}

Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/jit/indirectcalltransformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,21 @@ class IndirectCallTransformer
//
assert(!call->IsVirtual() && !call->IsDelegateInvoke());

// If this call is in tail position, see if we've created a recursive tail call
// candidate...
//
if (call->CanTailCall() && compiler->gtIsRecursiveCall(methodHnd))
{
compiler->setMethodHasRecursiveTailcall();
block->bbFlags |= BBF_RECURSIVE_TAILCALL;
JITDUMP("[%06u] is a recursive call in tail position\n", compiler->dspTreeID(call));
}
else
{
JITDUMP("[%06u] is%s in tail position and is%s recursive\n", compiler->dspTreeID(call),
call->CanTailCall() ? "" : " not", compiler->gtIsRecursiveCall(methodHnd) ? "" : " not");
}

// If the devirtualizer was unable to transform the call to invoke the unboxed entry, the inline info
// we set up may be invalid. We won't be able to inline anyways. So demote the call as an inline candidate.
//
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8065,7 +8065,7 @@ Compiler::fgWalkResult Compiler::lvaStressLclFldCB(GenTree** pTree, fgWalkData*
// TYP_BLK locals.
// TODO-Cleanup: Can probably be removed now since TYP_BLK does not
// exist anymore.
if (pComp->compMayConvertTailCallToLoop)
if (pComp->doesMethodHaveRecursiveTailcall())
{
varDsc->lvNoLclFldStress = true;
return WALK_CONTINUE;
Expand Down
19 changes: 16 additions & 3 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7450,11 +7450,16 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa
}
else
{
// Ensure we have a scratch block and then target the next
// block. Loop detection needs to see a pred out of the loop,
// We should have ensured the first BB was scratch
// in morph init...
//
assert(doesMethodHaveRecursiveTailcall());
assert(fgFirstBBisScratch());

// Loop detection needs to see a pred out of the loop,
// so mark the scratch block BBF_DONT_REMOVE to prevent empty
// block removal on it.
fgEnsureFirstBBisScratch();
//
fgFirstBB->bbFlags |= BBF_DONT_REMOVE;
block->SetJumpKindAndTarget(BBJ_ALWAYS, fgFirstBB->Next() DEBUG_ARG(this));
}
Expand Down Expand Up @@ -13854,6 +13859,14 @@ void Compiler::fgMorphBlocks()
lvSetMinOptsDoNotEnreg();
}

// Ensure the first BB is scratch if we might need it as a pred for
// the recursive tail call to loop optimization.
//
if (doesMethodHaveRecursiveTailcall())
{
fgEnsureFirstBBisScratch();
}

/*-------------------------------------------------------------------------
* Process all basic blocks in the function
*/
Expand Down