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
31 changes: 31 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11435,6 +11435,37 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
}
}

// If the call we're inlining was flagged as part of an enumerator
// GDV, and we're replacing it with another call, flag that call instead.
//
// This handles cases like ReadOnlyArray where GetEnumerator is
// expressed via another GetEnumerator call.
//
if ((info.compRetType == TYP_REF) && hasImpEnumeratorGdvLocalMap())
{
GenTree* const origCall = impInlineInfo->iciCall;
Compiler::NodeToUnsignedMap* const map = getImpEnumeratorGdvLocalMap();
unsigned enumeratorLcl = BAD_VAR_NUM;

if (map->Lookup(origCall, &enumeratorLcl))
{
GenTree* returnValue = op2;
if (returnValue->OperIs(GT_RET_EXPR))
{
returnValue = returnValue->AsRetExpr()->gtInlineCandidate;
}

if (returnValue->IsCall())
{
JITDUMP("Flagging [%06u] for enumerator cloning via V%02u\n", dspTreeID(returnValue),
enumeratorLcl);

map->Remove(origCall);
map->Set(returnValue, enumeratorLcl);
}
}
}

if (fgNeedReturnSpillTemp())
{
assert(info.compRetNativeType != TYP_VOID &&
Expand Down
22 changes: 19 additions & 3 deletions src/coreclr/jit/objectalloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4120,6 +4120,22 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)

// The allocation block must dominate all T appearances, save for the final T use.
//
// If we have an empty static case, we generalized slightly, and allow T appearances
// to be dominated by the allocation block's (unique) pred.
//
BasicBlock* domCheckBlock = allocBlock;
const char* domCheckBlockName = "alloc";
if ((info->m_allocTree->gtFlags & GTF_ALLOCOBJ_EMPTY_STATIC) != 0)
{
BasicBlock* const uniquePred = domCheckBlock->GetUniquePred(comp);

if (uniquePred != nullptr)
{
domCheckBlock = uniquePred;
domCheckBlockName = "alloc-pred";
}
}

for (unsigned lclNum : EnumeratorVarMap::KeyIteration(info->m_appearanceMap))
{
EnumeratorVar* ev = nullptr;
Expand All @@ -4138,10 +4154,10 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info)
continue;
}

if (!comp->m_domTree->Dominates(allocBlock, a->m_block))
if (!comp->m_domTree->Dominates(domCheckBlock, a->m_block))
{
JITDUMP("Alloc temp V%02u %s in " FMT_BB " not dominated by alloc " FMT_BB "\n", a->m_lclNum,
a->m_isDef ? "def" : "use", a->m_block->bbNum, allocBlock->bbNum);
JITDUMP("Alloc temp V%02u %s in " FMT_BB " not dominated by %s " FMT_BB "\n", a->m_lclNum,
a->m_isDef ? "def" : "use", a->m_block->bbNum, domCheckBlockName, domCheckBlock->bbNum);
return false;
}
}
Expand Down
Loading