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: Clean up liveness #103809

Merged
merged 8 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
4 changes: 0 additions & 4 deletions src/coreclr/jit/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,6 @@ void BasicBlock::CloneBlockState(Compiler* compiler, BasicBlock* to, const Basic
to->bbStkDepth = from->bbStkDepth;
to->bbCodeOffs = from->bbCodeOffs;
to->bbCodeOffsEnd = from->bbCodeOffsEnd;
VarSetOps::AssignAllowUninitRhs(compiler, to->bbScope, from->bbScope);
#ifdef DEBUG
to->bbTgtStkDepth = from->bbTgtStkDepth;
#endif // DEBUG
Expand Down Expand Up @@ -1470,7 +1469,6 @@ void BasicBlock::InitVarSets(Compiler* comp)
VarSetOps::AssignNoCopy(comp, bbVarDef, VarSetOps::MakeEmpty(comp));
VarSetOps::AssignNoCopy(comp, bbLiveIn, VarSetOps::MakeEmpty(comp));
VarSetOps::AssignNoCopy(comp, bbLiveOut, VarSetOps::MakeEmpty(comp));
VarSetOps::AssignNoCopy(comp, bbScope, VarSetOps::MakeEmpty(comp));

bbMemoryUse = emptyMemoryKindSet;
bbMemoryDef = emptyMemoryKindSet;
Expand Down Expand Up @@ -1672,15 +1670,13 @@ BasicBlock* BasicBlock::New(Compiler* compiler)
VarSetOps::AssignNoCopy(compiler, block->bbVarDef, VarSetOps::MakeEmpty(compiler));
VarSetOps::AssignNoCopy(compiler, block->bbLiveIn, VarSetOps::MakeEmpty(compiler));
VarSetOps::AssignNoCopy(compiler, block->bbLiveOut, VarSetOps::MakeEmpty(compiler));
VarSetOps::AssignNoCopy(compiler, block->bbScope, VarSetOps::MakeEmpty(compiler));
}
else
{
VarSetOps::AssignNoCopy(compiler, block->bbVarUse, VarSetOps::UninitVal());
VarSetOps::AssignNoCopy(compiler, block->bbVarDef, VarSetOps::UninitVal());
VarSetOps::AssignNoCopy(compiler, block->bbLiveIn, VarSetOps::UninitVal());
VarSetOps::AssignNoCopy(compiler, block->bbLiveOut, VarSetOps::UninitVal());
VarSetOps::AssignNoCopy(compiler, block->bbScope, VarSetOps::UninitVal());
}

block->bbMemoryUse = emptyMemoryKindSet;
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -1611,8 +1611,6 @@ struct BasicBlock : private LIR::Range
unsigned bbMemorySsaNumIn[MemoryKindCount]; // The SSA # of memory on entry to the block.
unsigned bbMemorySsaNumOut[MemoryKindCount]; // The SSA # of memory on exit from the block.

VARSET_TP bbScope; // variables in scope over the block

void InitVarSets(class Compiler* comp);

/* The following are the standard bit sets for dataflow analysis.
Expand Down
21 changes: 3 additions & 18 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5525,7 +5525,7 @@ class Compiler

void fgAddHandlerLiveVars(BasicBlock* block, VARSET_TP& ehHandlerLiveVars, MemoryKindSet& memoryLiveness);

void fgLiveVarAnalysis(bool updateInternalOnly = false);
void fgLiveVarAnalysis();

void fgComputeLifeCall(VARSET_TP& life, GenTreeCall* call);

Expand All @@ -5545,10 +5545,10 @@ class Compiler
void fgComputeLife(VARSET_TP& life,
GenTree* startNode,
GenTree* endNode,
VARSET_VALARG_TP volatileVars,
VARSET_VALARG_TP keepAliveVars,
bool* pStmtInfoDirty DEBUGARG(bool* treeModf));

void fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALARG_TP volatileVars);
void fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALARG_TP keepAliveVars);

bool fgTryRemoveNonLocal(GenTree* node, LIR::Range* blockRange);

Expand Down Expand Up @@ -5916,8 +5916,6 @@ class Compiler

PhaseStatus fgComputeDominators(); // Compute dominators

bool fgRemoveDeadBlocks(); // Identify and remove dead blocks.

public:
enum GCPollType
{
Expand Down Expand Up @@ -6678,19 +6676,6 @@ class Compiler

void fgMarkUseDef(GenTreeLclVarCommon* tree);

void fgBeginScopeLife(VARSET_TP* inScope, VarScopeDsc* var);
void fgEndScopeLife(VARSET_TP* inScope, VarScopeDsc* var);

void fgMarkInScope(BasicBlock* block, VARSET_VALARG_TP inScope);
void fgUnmarkInScope(BasicBlock* block, VARSET_VALARG_TP unmarkScope);

void fgExtendDbgScopes();
void fgExtendDbgLifetimes();

#ifdef DEBUG
void fgDispDebugScopes();
#endif // DEBUG

//-------------------------------------------------------------------------
//
// The following keeps track of any code we've added for things like array
Expand Down
105 changes: 0 additions & 105 deletions src/coreclr/jit/fgopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,111 +162,6 @@ bool Compiler::fgRemoveUnreachableBlocks(CanRemoveBlockBody canRemoveBlock)
return changed;
}

//------------------------------------------------------------------------
// fgRemoveDeadBlocks: Identify all the unreachable blocks and remove them.
//
bool Compiler::fgRemoveDeadBlocks()
{
JITDUMP("\n*************** In fgRemoveDeadBlocks()");

unsigned prevFgCurBBEpoch = fgCurBBEpoch;
EnsureBasicBlockEpoch();

BlockSet visitedBlocks(BlockSetOps::MakeEmpty(this));

jitstd::list<BasicBlock*> worklist(jitstd::allocator<void>(getAllocator(CMK_Reachability)));
worklist.push_back(fgFirstBB);

// Visit all the reachable blocks, everything else can be removed
while (!worklist.empty())
{
BasicBlock* block = *(worklist.begin());
worklist.pop_front();

if (BlockSetOps::IsMember(this, visitedBlocks, block->bbNum))
{
continue;
}

BlockSetOps::AddElemD(this, visitedBlocks, block->bbNum);

for (BasicBlock* succ : block->Succs(this))
{
worklist.push_back(succ);
}

// Add all the "EH" successors. For every `try`, add its handler (including filter) to the worklist.
if (bbIsTryBeg(block))
{
// Due to EH normalization, a block can only be the start of a single `try` region, with the exception
// of mutually-protect regions.
assert(block->hasTryIndex());
unsigned tryIndex = block->getTryIndex();
EHblkDsc* ehDsc = ehGetDsc(tryIndex);
for (;;)
{
worklist.push_back(ehDsc->ebdHndBeg);
if (ehDsc->HasFilter())
{
worklist.push_back(ehDsc->ebdFilter);
}
tryIndex = ehDsc->ebdEnclosingTryIndex;
if (tryIndex == EHblkDsc::NO_ENCLOSING_INDEX)
{
break;
}
ehDsc = ehGetDsc(tryIndex);
if (ehDsc->ebdTryBeg != block)
{
break;
}
}
}
}

// Track if there is any unreachable block. Even if it is marked with
// BBF_DONT_REMOVE, fgRemoveUnreachableBlocks() still removes the code
// inside the block. So this variable tracks if we ever found such blocks
// or not.
bool hasUnreachableBlock = false;

auto isBlockRemovable = [&](BasicBlock* block) -> bool {
const bool isVisited = BlockSetOps::IsMember(this, visitedBlocks, block->bbNum);
const bool isRemovable = !isVisited || (block->bbRefs == 0);

hasUnreachableBlock |= isRemovable;
return isRemovable;
};

bool changed = false;
unsigned iterationCount = 1;
do
{
JITDUMP("\nRemoving unreachable blocks for fgRemoveDeadBlocks iteration #%u\n", iterationCount);

// Just to be paranoid, avoid infinite loops; fall back to minopts.
if (iterationCount++ > 10)
{
noway_assert(!"Too many unreachable block removal loops");
}
changed = fgRemoveUnreachableBlocks(isBlockRemovable);
} while (changed);

#ifdef DEBUG
if (verbose && hasUnreachableBlock)
{
printf("\nAfter dead block removal:\n");
fgDispBasicBlocks(verboseTrees);
printf("\n");
}

fgVerifyHandlerTab();
fgDebugCheckBBlist(false);
#endif // DEBUG

return hasUnreachableBlock;
}

//-------------------------------------------------------------
// fgComputeDominators: Compute dominators
//
Expand Down
Loading
Loading