Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Put all CSEs into SSA #106637

Merged
merged 29 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ddf2b02
JIT: Put all CSEs into SSA
jakobbotsch Aug 19, 2024
8c8b9a0
Revert unnecessary change
jakobbotsch Aug 20, 2024
658b3ce
Avoid unnecessary flowgraph annotation recomputations
jakobbotsch Aug 20, 2024
6e23856
Speed up single-def case
jakobbotsch Aug 20, 2024
115291e
Add newline
jakobbotsch Aug 20, 2024
91f2352
Add cache
jakobbotsch Aug 20, 2024
2de17a2
Revert "Add cache"
jakobbotsch Aug 20, 2024
21f4d95
Fix assert, write some more docs
jakobbotsch Aug 20, 2024
64eb25e
Add incremental liveness updating as well
jakobbotsch Aug 21, 2024
caa8dd3
Revert "Add incremental liveness updating as well"
jakobbotsch Aug 21, 2024
cb993e0
Merge branch 'main' of github.com:dotnet/runtime into ssa-updating
jakobbotsch Aug 23, 2024
49e573b
Merge branch 'main' of github.com:dotnet/runtime into ssa-updating
jakobbotsch Oct 7, 2024
727179d
Merge branch 'main' of github.com:dotnet/runtime into ssa-updating
jakobbotsch Oct 31, 2024
0869ba6
Remove comment
jakobbotsch Oct 31, 2024
f5d2685
Add function header
jakobbotsch Oct 31, 2024
96ac716
Reapply "Add incremental liveness updating as well"
jakobbotsch Nov 6, 2024
a65ff9e
Compute liveness for SSA-inserted locals
jakobbotsch Nov 6, 2024
c9c22fc
Run jit-format
jakobbotsch Nov 6, 2024
03a05da
Merge branch 'main' of github.com:dotnet/runtime into ssa-updating
jakobbotsch Nov 6, 2024
e811f1a
Switch bbNum -> bbID
jakobbotsch Nov 6, 2024
cd0cd44
Fix liveness marking
jakobbotsch Nov 6, 2024
2b7f821
Fix hash code
jakobbotsch Nov 6, 2024
69bbc00
Revert unnecessary change
jakobbotsch Nov 6, 2024
e0d1442
Skip SSA insertion for large IDFs
jakobbotsch Nov 6, 2024
55fa27b
Nit
jakobbotsch Nov 6, 2024
0e6d44f
Fix build
jakobbotsch Nov 6, 2024
2e1ba4c
Feedback on remark
jakobbotsch Nov 6, 2024
f8e5a03
Fix live-in check
jakobbotsch Nov 6, 2024
63fca5d
Add assert that fgFirstBB does not have live-in locals added
jakobbotsch Nov 7, 2024
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
50 changes: 50 additions & 0 deletions src/coreclr/jit/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,56 @@ FlowEdge* Compiler::BlockDominancePreds(BasicBlock* blk)
return res;
}

//------------------------------------------------------------------------
// IsInsertedSsaLiveIn: See if a local is marked as being live-in to a block in
// the side table with locals inserted into SSA.
//
// Arguments:
// block - The block
// lclNum - The local
//
// Returns:
// True if the local is marked as live-in to that block
//
bool Compiler::IsInsertedSsaLiveIn(BasicBlock* block, unsigned lclNum)
{
assert(lvaGetDesc(lclNum)->lvInSsa);

if (m_insertedSsaLocalsLiveIn == nullptr)
{
return false;
}

return m_insertedSsaLocalsLiveIn->Lookup(BasicBlockLocalPair(block, lclNum));
}

//------------------------------------------------------------------------
// AddInsertedSsaLiveIn: Mark as local that was inserted into SSA as being
// live-in to a block.
//
// Arguments:
// block - The block
// lclNum - The local
//
// Returns:
// True if this was added anew; false if the local was already marked as such.
//
bool Compiler::AddInsertedSsaLiveIn(BasicBlock* block, unsigned lclNum)
{
if (m_insertedSsaLocalsLiveIn == nullptr)
{
m_insertedSsaLocalsLiveIn = new (this, CMK_SSA) BasicBlockLocalPairSet(getAllocator(CMK_SSA));
}

if (m_insertedSsaLocalsLiveIn->Set(BasicBlockLocalPair(block, lclNum), true, BasicBlockLocalPairSet::Overwrite))
{
return false;
}

JITDUMP("Marked V%02u as live into " FMT_BB "\n", lclNum, block->bbNum);
return true;
}

//------------------------------------------------------------------------
// IsLastHotBlock: see if this is the last block before the cold section
//
Expand Down
30 changes: 30 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2948,6 +2948,35 @@ class Compiler
return m_dominancePreds;
}

struct BasicBlockLocalPair
{
BasicBlock* Block;
unsigned LclNum;

BasicBlockLocalPair(BasicBlock* block, unsigned lclNum)
: Block(block)
, LclNum(lclNum)
{
}

static bool Equals(const BasicBlockLocalPair& x, const BasicBlockLocalPair& y)
{
return (x.Block == y.Block) && (x.LclNum == y.LclNum);
}
static unsigned GetHashCode(const BasicBlockLocalPair& val)
{
unsigned hash = val.Block->bbID;
hash ^= val.LclNum + 0x9e3779b9 + (hash << 19) + (hash >> 13);
return hash;
}
};

typedef JitHashTable<BasicBlockLocalPair, BasicBlockLocalPair, bool> BasicBlockLocalPairSet;

BasicBlockLocalPairSet* m_insertedSsaLocalsLiveIn = nullptr;
bool IsInsertedSsaLiveIn(BasicBlock* block, unsigned lclNum);
bool AddInsertedSsaLiveIn(BasicBlock* block, unsigned lclNum);

void* ehEmitCookie(BasicBlock* block);
UNATIVE_OFFSET ehCodeOffset(BasicBlock* block);

Expand Down Expand Up @@ -7706,6 +7735,7 @@ class Compiler
LoopLocalOccurrences* loopLocals);
bool optCanAndShouldChangeExitTest(GenTree* cond, bool dump);
bool optLocalHasNonLoopUses(unsigned lclNum, FlowGraphNaturalLoop* loop, LoopLocalOccurrences* loopLocals);
bool optLocalIsLiveIntoBlock(unsigned lclNum, BasicBlock* block);

bool optWidenIVs(ScalarEvolutionContext& scevContext, FlowGraphNaturalLoop* loop, LoopLocalOccurrences* loopLocals);
bool optWidenPrimaryIV(FlowGraphNaturalLoop* loop,
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6623,9 +6623,9 @@ FlowGraphDominanceFrontiers::FlowGraphDominanceFrontiers(FlowGraphDominatorTree*
// Data structure representing dominance frontiers.
//
// Remarks:
// Recall that the dominance frontier of a block B is the set of blocks
// B3 such that there exists some B2 s.t. B3 is a successor of B2, and
// B dominates B2. Note that this dominance need not be strict -- B2
// Recall that the dominance frontier of a block B is the set of blocks B3
// such that there exists some B2 s.t. B3 is a successor of B2, and B
// dominates B2 but not B3. Note that this dominance need not be strict -- B2
// and B may be the same node.
//
// In other words, a block B' is in DF(B) if B dominates an immediate
Expand Down
46 changes: 36 additions & 10 deletions src/coreclr/jit/inductionvariableopts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,13 +391,10 @@ bool Compiler::optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop)
{
LclVarDsc* dsc = lvaGetDesc(lclNum);

if (!dsc->lvTracked)
{
return false;
}
assert(dsc->lvInSsa);

BasicBlockVisit result = loop->VisitRegularExitBlocks([=](BasicBlock* exit) {
if (!VarSetOps::IsMember(this, exit->bbLiveIn, dsc->lvVarIndex))
if (!optLocalIsLiveIntoBlock(lclNum, exit))
{
JITDUMP(" Exit " FMT_BB " does not need a sink; V%02u is not live-in\n", exit->bbNum, lclNum);
return BasicBlockVisit::Continue;
Expand Down Expand Up @@ -427,7 +424,7 @@ bool Compiler::optCanSinkWidenedIV(unsigned lclNum, FlowGraphNaturalLoop* loop)
block->VisitAllSuccs(this, [=](BasicBlock* succ) {
if (!loop->ContainsBlock(succ) && bbIsHandlerBeg(succ))
{
assert(!VarSetOps::IsMember(this, succ->bbLiveIn, dsc->lvVarIndex) &&
assert(!optLocalIsLiveIntoBlock(lclNum, succ) &&
"Candidate IV for widening is live into exceptional exit");
}

Expand Down Expand Up @@ -539,8 +536,10 @@ bool Compiler::optIsIVWideningProfitable(unsigned lclNum,

// Now account for the cost of sinks.
LclVarDsc* dsc = lvaGetDesc(lclNum);
assert(dsc->lvInSsa);

loop->VisitRegularExitBlocks([&](BasicBlock* exit) {
if (VarSetOps::IsMember(this, exit->bbLiveIn, dsc->lvVarIndex))
if (optLocalIsLiveIntoBlock(lclNum, exit))
{
savedSize -= ExtensionSize;
savedCost -= exit->getBBWeight(this) * ExtensionCost;
Expand Down Expand Up @@ -588,8 +587,10 @@ bool Compiler::optIsIVWideningProfitable(unsigned lclNum,
void Compiler::optSinkWidenedIV(unsigned lclNum, unsigned newLclNum, FlowGraphNaturalLoop* loop)
{
LclVarDsc* dsc = lvaGetDesc(lclNum);
assert(dsc->lvInSsa);

loop->VisitRegularExitBlocks([=](BasicBlock* exit) {
if (!VarSetOps::IsMember(this, exit->bbLiveIn, dsc->lvVarIndex))
if (!optLocalIsLiveIntoBlock(lclNum, exit))
{
return BasicBlockVisit::Continue;
}
Expand Down Expand Up @@ -1289,13 +1290,14 @@ bool Compiler::optLocalHasNonLoopUses(unsigned lclNum, FlowGraphNaturalLoop* loo
return true;
}

if (!varDsc->lvTracked)
if (!varDsc->lvTracked && !varDsc->lvInSsa)
{
// We do not have liveness we can use for this untracked local.
return true;
}

BasicBlockVisit visitResult = loop->VisitRegularExitBlocks([=](BasicBlock* block) {
if (VarSetOps::IsMember(this, block->bbLiveIn, varDsc->lvVarIndex))
if (optLocalIsLiveIntoBlock(lclNum, block))
{
return BasicBlockVisit::Abort;
}
Expand All @@ -1315,6 +1317,30 @@ bool Compiler::optLocalHasNonLoopUses(unsigned lclNum, FlowGraphNaturalLoop* loo
return false;
}

//------------------------------------------------------------------------
// optLocalIsLiveIntoBlock:
// Check if a local is live into a block. Required liveness information for the local to be present
// (either because of it being tracked, or from being an SSA-inserted local).
//
// Parameters:
// lclNum - The local
// block - The block
//
// Returns:
// True if the local is live into that block.
//
bool Compiler::optLocalIsLiveIntoBlock(unsigned lclNum, BasicBlock* block)
{
LclVarDsc* dsc = lvaGetDesc(lclNum);
if (dsc->lvTracked)
{
return VarSetOps::IsMember(this, block->bbLiveIn, dsc->lvVarIndex);
}

assert(dsc->lvInSsa);
return IsInsertedSsaLiveIn(block, lclNum);
}

struct CursorInfo
{
BasicBlock* Block;
Expand Down
Loading
Loading