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

Generalize loop pre-header creation and loop hoisting #62560

Merged
Merged
47 changes: 39 additions & 8 deletions src/coreclr/jit/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,18 +575,49 @@ unsigned BasicBlock::dspCheapPreds()
return count;
}

/*****************************************************************************
*
* Display the basic block successors.
*/

//------------------------------------------------------------------------
// dspSuccs: Display the basic block successors.
//
// Arguments:
// compiler - compiler instance; passed to NumSucc(Compiler*) -- see that function for implications.
//
void BasicBlock::dspSuccs(Compiler* compiler)
{
bool first = true;
for (BasicBlock* const succ : Succs(compiler))

// If this is a switch, we don't want to call `Succs(Compiler*)` because it will eventually call
// `GetSwitchDescMap()`, and that will have the side-effect of allocating the unique switch descriptor map
// and/or compute this switch block's unique succ set if it is not present. Debug output functions should
// never have an effect on codegen. We also don't want to assume the unique succ set is accurate, so we
// compute it ourselves here.
if (bbJumpKind == BBJ_SWITCH)
{
// Create a set with all the successors. Don't use BlockSet, so we don't need to worry
// about the BlockSet epoch.
unsigned bbNumMax = compiler->impInlineRoot()->fgBBNumMax;
BitVecTraits bitVecTraits(bbNumMax + 1, compiler);
BitVec uniqueSuccBlocks(BitVecOps::MakeEmpty(&bitVecTraits));
for (BasicBlock* const bTarget : SwitchTargets())
{
BitVecOps::AddElemD(&bitVecTraits, uniqueSuccBlocks, bTarget->bbNum);
}
BitVecOps::Iter iter(&bitVecTraits, uniqueSuccBlocks);
unsigned bbNum = 0;
while (iter.NextElem(&bbNum))
{
// Note that we will output switch successors in increasing numerical bbNum order, which is
// not related to their order in the bbJumpSwt->bbsDstTab table.
printf("%s" FMT_BB, first ? "" : ",", bbNum);
first = false;
}
}
else
{
printf("%s" FMT_BB, first ? "" : ",", succ->bbNum);
first = false;
for (BasicBlock* const succ : Succs(compiler))
{
printf("%s" FMT_BB, first ? "" : ",", succ->bbNum);
first = false;
}
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ enum BasicBlockFlags : unsigned __int64

// Flags that relate blocks to loop structure.

BBF_LOOP_FLAGS = BBF_LOOP_PREHEADER | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1,
BBF_LOOP_FLAGS = BBF_LOOP_PREHEADER | BBF_LOOP_HEAD | BBF_LOOP_CALL0 | BBF_LOOP_CALL1 | BBF_LOOP_ALIGN,

// Flags to update when two blocks are compacted

Expand Down Expand Up @@ -1001,6 +1001,16 @@ struct BasicBlock : private LIR::Range
bbHndIndex = from->bbHndIndex;
}

void copyTryIndex(const BasicBlock* from)
{
bbTryIndex = from->bbTryIndex;
}

void copyHndIndex(const BasicBlock* from)
{
bbHndIndex = from->bbHndIndex;
}

static bool sameTryRegion(const BasicBlock* blk1, const BasicBlock* blk2)
{
return blk1->bbTryIndex == blk2->bbTryIndex;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/clrjit.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Documentation for VS debugger format specifiers: https://docs.microsoft.com/en-u

<Type Name="BasicBlock">
<DisplayString Condition="bbJumpKind==BBJ_COND || bbJumpKind==BBJ_ALWAYS || bbJumpKind==BBJ_LEAVE || bbJumpKind==BBJ_EHCATCHRET || bbJumpKind==BBJ_CALLFINALLY">BB{bbNum,d}->BB{bbJumpDest->bbNum,d}; {bbJumpKind,en}</DisplayString>
<DisplayString Condition="bbJumpKind==BBJ_SWITCH">BB{bbNum,d}; {bbJumpKind,en}; {bbJumpSwt->bbsCount} cases</DisplayString>
<DisplayString>BB{bbNum,d}; {bbJumpKind,en}</DisplayString>
</Type>

Expand Down
16 changes: 8 additions & 8 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4898,10 +4898,14 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
//
DoPhase(this, PHASE_COMPUTE_REACHABILITY, &Compiler::fgComputeReachability);

// Scale block weights and mark run rarely blocks.
//
DoPhase(this, PHASE_SET_BLOCK_WEIGHTS, &Compiler::optSetBlockWeights);

// Discover and classify natural loops (e.g. mark iterative loops as such). Also marks loop blocks
// and sets bbWeight to the loop nesting levels.
//
DoPhase(this, PHASE_FIND_LOOPS, &Compiler::optFindLoops);
DoPhase(this, PHASE_FIND_LOOPS, &Compiler::optFindLoopsPhase);

// Clone loops with optimization opportunities, and choose one based on dynamic condition evaluation.
//
Expand Down Expand Up @@ -5444,20 +5448,16 @@ void Compiler::ResetOptAnnotations()
// The intent of this method is to update loop structure annotations, and those
// they depend on; these annotations may have become stale during optimization,
// and need to be up-to-date before running another iteration of optimizations.

//
void Compiler::RecomputeLoopInfo()
{
assert(opts.optRepeat);
assert(JitConfig.JitOptRepeatCount() > 0);
// Recompute reachability sets, dominators, and loops.
optLoopCount = 0;
optResetLoopInfo();
fgDomsComputed = false;
for (BasicBlock* const block : Blocks())
{
block->bbFlags &= ~BBF_LOOP_FLAGS;
block->bbNatLoopNum = BasicBlock::NOT_IN_LOOP;
}
fgComputeReachability();
optSetBlockWeights();
// Rebuild the loop tree annotations themselves
optFindLoops();
}
Expand Down
Loading