8000 JIT: Read back parameter register replacements eagerly (#112501) · dotnet/runtime@1eadeff · GitHub
[go: up one dir, main page]

Skip to content

Commit 1eadeff

Browse files
authored
JIT: Read back parameter register replacements eagerly (#112501)
Have physical promotion read replacements that map to parameter registers back eagerly in the entry basic block. Reading these back initially makes it more likely that the backend will be able to substitute directly for registers.
1 parent ea43e17 commit 1eadeff

File tree

2 files changed

+84
-54
lines changed

2 files changed

+84
-54
lines changed

src/coreclr/jit/promotion.cpp

Lines changed: 80 additions & 50 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ class LocalUses
777777
else if (lcl->lvIsParam)
778778
{
779779
// For parameters, the backend may be able to map it directly from a register.
780-
if (MapsToRegister(comp, access, lclNum))
780+
if (Promotion::MapsToParameterRegister(comp, lclNum, access.Offset, access.AccessType))
781781
{
782782
// No promotion will result in a store to stack in the prolog.
783783
costWithout += COST_STRUCT_ACCESS_CYCLES * comp->fgFirstBB->getBBWeight(comp);
@@ -1022,46 +1022,6 @@ class LocalUses
10221022

10231023
return nullptr;
10241024
}
1025-
1026-
//------------------------------------------------------------------------
1027-
// MapsToRegister:
1028-
// Check if a specific access in the specified parameter local is
1029-
// expected to map to a register.
1030-
//
1031-
// Parameters:
1032-
// comp - Compiler instance
1033-
// access - Access in the local
1034-
// lclNum - Parameter lcl num
1035-
//
1036-
// Returns:
1037-
// Pointer to a matching access, or nullptr if no match was found.
1038-
//
1039-
bool MapsToRegister(Compiler* comp, const Access& access, unsigned lclNum)
1040-
{
1041-
assert(lclNum < comp->info.compArgsCount);
1042-
1043-
if (comp->lvaIsImplicitByRefLocal(lclNum))
1044-
{
1045-
return false;
1046-
}
1047-
1048-
const ABIPassingInformation& abiInfo = comp->lvaGetParameterABIInfo(lclNum);
1049-
if (abiInfo.HasAnyStackSegment())
1050-
{
1051-
return false;
1052-
}
1053-
1054-
for (const ABIPassingSegment& seg : abiInfo.Segments())
1055-
{
1056-
if ((access.Offset == seg.Offset) && (genTypeSize(access.AccessType) == seg.Size) &&
1057-
(varTypeUsesIntReg(access.AccessType) == genIsValidIntReg(seg.GetRegister())))
1058-
{
1059-
return true;
1060-
}
1061-
}
1062-
1063-
return false;
1064-
}
10651025
};
10661026

10671027
// Struct used to save all struct stores involving physical promotion candidates.
@@ -1674,7 +1634,10 @@ GenTree* Promotion::CreateReadBack(Compiler* compiler, unsigned structLclNum, co
16741634
// Parameters:
16751635
// block - The block
16761636
//
1677-
void ReplaceVisitor::StartBlock(BasicBlock* block)
1637+
// Returns:
1638+
// Statement in block to start from.
1639+
//
1640+
Statement* ReplaceVisitor::StartBlock(BasicBlock* block)
16781641
{
16791642
m_currentBlock = block;
16801643

@@ -1697,9 +1660,11 @@ void ReplaceVisitor::StartBlock(BasicBlock* block)
16971660
// when we start the initial BB.
16981661
if (block != m_compiler->fgFirstBB)
16991662
{
1700-
return;
1663+
return block->firstStmt();
17011664
}
17021665

1666+
Statement* lastInsertedStmt = nullptr;
1667+
17031668
for (AggregateInfo* agg : m_aggregates)
17041669
{
17051670
LclVarDsc* dsc = m_compiler->lvaGetDesc(agg->LclNum);
@@ -1708,24 +1673,48 @@ void ReplaceVisitor::StartBlock(BasicBlock* block)
17081673
continue;
17091674
}
17101675

1711-
JITDUMP("Marking fields of %s V%02u as needing read-back in entry BB " FMT_BB "\n",
1712-
dsc->lvIsParam ? "parameter" : "OSR-local", agg->LclNum, block->bbNum);
1676+
JITDUMP("Processing fields of %s V%02u in entry BB " FMT_BB "\n", dsc->lvIsParam ? "parameter" : "OSR-local",
1677+
agg->LclNum, block->bbNum);
17131678

17141679
for (size_t i = 0; i < agg->Replacements.size(); i++)
17151680
{
17161681
Replacement& rep = agg->Replacements[i];
17171682
ClearNeedsWriteBack(rep);
1718-
if (m_liveness->IsReplacementLiveIn(block, agg->LclNum, (unsigned)i))
1683+
if (!m_liveness->IsReplacementLiveIn(block, agg->LclNum, (unsigned)i))
1684+
{
1685+
JITDUMP(" V%02u (%s) ignored because it is not live-in to entry BB\n", rep.LclNum, rep.Description);
1686+
continue;
1687+
}
1688+
1689+
if (!dsc->lvIsParam ||
1690+
!Promotion::MapsToParameterRegister(m_compiler, agg->LclNum, rep.Offset, rep.AccessType))
17191691
{
17201692
SetNeedsReadBack(rep);
1721-
JITDUMP(" V%02u (%s) marked\n", rep.LclNum, rep.Description);
1693+
JITDUMP(" V%02u (%s) marked as needing read back\n", rep.LclNum, rep.Description);
1694+
continue;
1695+
}
1696+
1697+
// Insert read backs of parameters mapping to registers eagerly to
1698+
// set the backend up for recognizing these as register accesses.
1699+
GenTree* readBack = Promotion::CreateReadBack(m_compiler, agg->LclNum, rep);
1700+
Statement* stmt = m_compiler->fgNewStmtFromTree(readBack);
1701+
JITDUMP(" V%02u (%s) is read back eagerly because it is a register parameter\n", rep.LclNum,
1702+
rep.Description);
1703+
DISPSTMT(stmt);
1704+
if (lastInsertedStmt == nullptr)
1705+
{
1706+
m_compiler->fgInsertStmtAtBeg(block, stmt);
17221707
}
17231708
else
17241709
{
1725-
JITDUMP(" V%02u (%s) not marked (not live-in to entry BB)\n", rep.LclNum, rep.Description);
1710+
m_compiler->fgInsertStmtAfter(block, lastInsertedStmt, stmt);
17261711
}
1712+
lastInsertedStmt = stmt;
17271713
}
17281714
}
1715+
1716+
// Skip all the eager read-backs if any were inserted.
1717+
return lastInsertedStmt == nullptr ? block->firstStmt() : lastInsertedStmt->GetNextStmt();
17291718
}
17301719

17311720
//------------------------------------------------------------------------
@@ -3031,13 +3020,13 @@ PhaseStatus Promotion::Run()
30313020
ReplaceVisitor replacer(this, aggregates, &liveness);
30323021
for (BasicBlock* bb : m_compiler->Blocks())
30333022
{
3034-
replacer.StartBlock(bb);
3023+
Statement* firstStmt = replacer.StartBlock(bb);
30353024

30363025
JITDUMP("\nReplacing in ");
30373026
DBEXEC(m_compiler->verbose, bb->dspBlockHeader(m_compiler));
30383027
JITDUMP("\n");
30393028

3040-
for (Statement* stmt : bb->Statements())
3029+
for (Statement* stmt : StatementList(firstStmt))
30413030
{
30423031
replacer.StartStatement(stmt);
30433032

@@ -3143,6 +3132,47 @@ GenTree* Promotion::EffectiveUser(Compiler::GenTreeStack& ancestors)
31433132
return nullptr;
31443133
}
31453134

3135+
//------------------------------------------------------------------------
3136+
// MapsToParameterRegister:
3137+
// Check if a specific access in the specified parameter local is
3138+
// expected to map to a register.
3139+
//
3140+
// Parameters:
3141+
// comp - Compiler instance
3142+
// lclNum - Local being accessed into
3143+
// offset - Offset being accessed at
3144+
// accessType - Type of access
3145+
//
3146+
// Returns:
3147+
// True if the access can be efficiently done via a parameter register.
3148+
//
3149+
bool Promotion::MapsToParameterRegister(Compiler* comp, unsigned lclNum, unsigned offset, var_types accessType)
3150+
{
3151+
assert(lclNum < comp->info.compArgsCount);
3152+
3153+
if (comp->opts.IsOSR())
3154+
{
3155+
return false;
3156+
}
3157+
3158+
const ABIPassingInformation& abiInfo = comp->lvaGetParameterABIInfo(lclNum);
3159+
if (abiInfo.IsPassedByReference() || abiInfo.HasAnyStackSegment())
3160+
{
3161+
return false;
3162+
}
3163+
3164+
for (const ABIPassingSegment& seg : abiInfo.Segments())
3165+
{
3166+
if ((offset == seg.Offset) && (genTypeSize(accessType) == seg.Size) &&
3167+
(varTypeUsesIntReg(accessType) == genIsValidIntReg(seg.GetRegister())))
3168+
{
3169+
return true;
3170+
}
3171+
}
3172+
3173+
return false;
3174+
}
3175+
31463176
// Promotion::ExplicitlyZeroInitReplacementLocals:
31473177
// Insert IR to zero out replacement locals if necessary.
31483178
//

src/coreclr/jit/promotion.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class Promotion
154154

155155
static bool IsCandidateForPhysicalPromotion(LclVarDsc* dsc);
156156
static GenTree* EffectiveUser(Compiler::GenTreeStack& ancestors);
157-
157+
static bool MapsToParameterRegister(Compiler* comp, unsigned lclNum, unsigned offs, var_types accessType);
158158
public:
159159
explicit Promotion(Compiler* compiler)
160160
: m_compiler(compiler)
@@ -274,9 +274,9 @@ class ReplaceVisitor : public GenTreeVisitor<ReplaceVisitor>
274274
return m_mayHaveForwardSub;
275275
}
276276

277-
void StartBlock(BasicBlock* block);
278-
void EndBlock();
279-
void StartStatement(Statement* stmt);
277+
Statement* StartBlock(BasicBlock* block);
278+
void EndBlock();
279+
void StartStatement(Statement* stmt);
280280

281281
fgWalkResult PostOrderVisit(GenTree** use, GenTree* user);
282282

0 commit comments

Comments
 (0)
0