Skip to content

Commit

Permalink
Always create loop pre-header
Browse files Browse the repository at this point in the history
As part of finding natural loops and creating the loop
table, create a loop pre-header for every loop. This
simplifies a lot of downstream phases, as the loop
pre-header will be guaranteed to exist, and will already
exist in the dominator tree.

Introduce code to preserve an empty pre-header block through
the optimization phases.

Remove now unnecessary code in hoisting and elsewhere.

Fixes dotnet#77033, dotnet#62665
  • Loading branch information
BruceForstall committed Apr 6, 2023
1 parent e45e5db commit ae9c728
Showing 1 changed file with 13 additions and 13 deletions.
26 changes: 13 additions & 13 deletions src/coreclr/jit/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2687,19 +2687,20 @@ void Compiler::optFindNaturalLoops()
fgUpdateChangedFlowGraph(FlowGraphUpdates::COMPUTE_DOMS);
}

if (false /* pre-header stress */)
// Create loop pre-header for every loop.
bool modForPreHeader = false;
for (unsigned loopInd = 0; loopInd < optLoopCount; loopInd++)
{
// Stress mode: aggressively create loop pre-header for every loop.
for (unsigned loopInd = 0; loopInd < optLoopCount; loopInd++)
if (fgCreateLoopPreHeader(loopInd))
{
fgCreateLoopPreHeader(loopInd);
}

if (fgModified)
{
fgUpdateChangedFlowGraph(FlowGraphUpdates::COMPUTE_DOMS);
modForPreHeader = true;
}
}
if (modForPreHeader)
{
// The predecessors were maintained in fgCreateLoopPreHeader; don't rebuild them.
fgUpdateChangedFlowGraph(FlowGraphUpdates::COMPUTE_DOMS);
}

#ifdef DEBUG
if (verbose && (optLoopCount > 0))
Expand Down Expand Up @@ -7992,6 +7993,8 @@ bool Compiler::optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNSet* loopVnInv
// If there already exists a block that meets the pre-header requirements, that block is marked
// as a pre-header, and no flow graph modification is made.
//
// A loop with a pre-header has the flag LPFLG_HAS_PREHEAD, and its pre-header block has the flag BBF_LOOP_PREHEADER.
//
// Note that the pre-header block can be in a different EH region from blocks in the loop, including the
// entry block. Code doing hoisting is required to check the EH legality of hoisting to the pre-header
// before doing so.
Expand All @@ -8003,10 +8006,6 @@ bool Compiler::optVNIsLoopInvariant(ValueNum vn, unsigned lnum, VNSet* loopVnInv
// handle queries about the pre-header dominating other blocks, even without re-computing dominators.
// The preds lists have been maintained.
//
// Currently, if you create a pre-header but don't put any code in it, any subsequent fgUpdateFlowGraph()
// pass might choose to compact the empty pre-header with a predecessor block. That is, a pre-header
// block might disappear if not used.
//
// The code does not depend on the order of the BasicBlock bbNum.
//
// Arguments:
Expand Down Expand Up @@ -8222,6 +8221,7 @@ bool Compiler::fgCreateLoopPreHeader(unsigned lnum)
// This is sufficient because any definition participating in SSA that flowed
// into the phi via the loop header block will now flow through the preheader
// block from the header block.
// TODO: if we always create and maintain pre-headers before SSA, can we delete this?

for (Statement* const stmt : top->Statements())
{
Expand Down

0 comments on commit ae9c728

Please sign in to comment.