Skip to content

Commit b2a5499

Browse files
authored
Loop alignment: Handle blocks added in loop as part of split edges of LSRA (#55047)
* Handle blocks added in loop as part of split edges of LSRA If there are new blocks added by LSRA and modifies the flow of blocks that are in loop, then make sure that we do not align such loops if they intersect with last aligned loop. * Retain LOOP_ALIGN flag of loops whose start are same * jit format * review feedback
1 parent 9dd6d2e commit b2a5499

File tree

2 files changed

+90
-36
lines changed

2 files changed

+90
-36
lines changed

src/coreclr/jit/emit.cpp

Lines changed: 84 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,9 +1023,9 @@ void emitter::emitBegFN(bool hasFramePtr
10231023
emitIGbuffSize = 0;
10241024

10251025
#if FEATURE_LOOP_ALIGN
1026-
emitLastAlignedIgNum = 0;
1027-
emitLastInnerLoopStartIgNum = 0;
1028-
emitLastInnerLoopEndIgNum = 0;
1026+
emitLastAlignedIgNum = 0;
1027+
emitLastLoopStart = 0;
1028+
emitLastLoopEnd = 0;
10291029
#endif
10301030

10311031
/* Record stack frame info (the temp size is just an estimate) */
@@ -4820,58 +4820,112 @@ unsigned emitter::getLoopSize(insGroup* igLoopHeader, unsigned maxLoopSize DEBUG
48204820
// if currIG has back-edge to dstIG.
48214821
//
48224822
// Notes:
4823-
// If the current loop encloses a loop that is already marked as align, then remove
4824-
// the alignment flag present on IG before dstIG.
4823+
// Despite we align only inner most loop, we might see intersected loops because of control flow
4824+
// re-arrangement like adding a split edge in LSRA.
4825+
//
4826+
// If there is an intersection of current loop with last loop that is already marked as align,
4827+
// then *do not align* one of the loop that completely encloses the other one. Or if they both intersect,
4828+
// then *do not align* either of them because since the flow is complicated enough that aligning one of them
4829+
// will not improve the performance.
48254830
//
48264831
void emitter::emitSetLoopBackEdge(BasicBlock* loopTopBlock)
48274832
{
4828-
insGroup* dstIG = (insGroup*)loopTopBlock->bbEmitCookie;
4833+
insGroup* dstIG = (insGroup*)loopTopBlock->bbEmitCookie;
4834+
bool alignCurrentLoop = true;
4835+
bool alignLastLoop = true;
48294836

48304837
// With (dstIG != nullptr), ensure that only back edges are tracked.
48314838
// If there is forward jump, dstIG is not yet generated.
48324839
//
48334840
// We don't rely on (block->bbJumpDest->bbNum <= block->bbNum) because the basic
48344841
// block numbering is not guaranteed to be sequential.
4835-
48364842
if ((dstIG != nullptr) && (dstIG->igNum <= emitCurIG->igNum))
48374843
{
48384844
unsigned currLoopStart = dstIG->igNum;
48394845
unsigned currLoopEnd = emitCurIG->igNum;
48404846

48414847
// Only mark back-edge if current loop starts after the last inner loop ended.
4842-
if (emitLastInnerLoopEndIgNum < currLoopStart)
4848+
if (emitLastLoopEnd < currLoopStart)
48434849
{
48444850
emitCurIG->igLoopBackEdge = dstIG;
48454851

48464852
JITDUMP("** IG%02u jumps back to IG%02u forming a loop.\n", currLoopEnd, currLoopStart);
48474853

4848-
emitLastInnerLoopStartIgNum = currLoopStart;
4849-
emitLastInnerLoopEndIgNum = currLoopEnd;
4854+
emitLastLoopStart = currLoopStart;
4855+
emitLastLoopEnd = currLoopEnd;
4856+
}
4857+
else if (currLoopStart == emitLastLoopStart)
4858+
{
4859+
// Note: If current and last loop starts at same point,
4860+
// retain the alignment flag of the smaller loop.
4861+
// |
4862+
// .---->|<----.
4863+
// last | | |
4864+
// loop | | | current
4865+
// .---->| | loop
4866+
// | |
4867+
// |-----.
4868+
//
4869+
}
4870+
else if ((currLoopStart < emitLastLoopStart) && (emitLastLoopEnd < currLoopEnd))
4871+
{
4872+
// if current loop completely encloses last loop,
4873+
// then current loop should not be aligned.
4874+
alignCurrentLoop = false;
4875+
}
4876+
else if ((emitLastLoopStart < currLoopStart) && (currLoopEnd < emitLastLoopEnd))
4877+
{
4878+
// if last loop completely encloses current loop,
4879+
// then last loop should not be aligned.
4880+
alignLastLoop = false;
4881+
}
4882+
else
4883+
{
4884+
// The loops intersect and should not align either of the loops
4885+
alignLastLoop = false;
4886+
alignCurrentLoop = false;
48504887
}
4851-
// Otherwise, mark the dstIG->prevIG as no alignment needed.
4852-
//
4853-
// Note: If current loop's back-edge target is same as emitLastInnerLoopStartIgNum,
4854-
// retain the alignment flag of dstIG->prevIG so the loop
4855-
// (emitLastInnerLoopStartIgNum ~ emitLastInnerLoopEndIgNum) is still aligned.
4856-
else if (emitLastInnerLoopStartIgNum != currLoopStart)
4857-
{
4858-
// Find the IG before dstIG...
4859-
instrDescAlign* alignInstr = emitAlignList;
4860-
while ((alignInstr != nullptr) && (alignInstr->idaIG->igNext != dstIG))
4861-
{
4862-
alignInstr = alignInstr->idaNext;
4863-
}
48644888

4865-
// ...and clear the IGF_LOOP_ALIGN flag
4866-
if (alignInstr != nullptr)
4889+
if (!alignLastLoop || !alignCurrentLoop)
4890+
{
4891+
instrDescAlign* alignInstr = emitAlignList;
4892+
bool markedLastLoop = alignLastLoop;
4893+
bool markedCurrLoop = alignCurrentLoop;
4894+
while ((alignInstr != nullptr))
48674895
{
4868-
assert(alignInstr->idaIG->igNext == dstIG);
4869-
alignInstr->idaIG->igFlags &= ~IGF_LOOP_ALIGN;
4896+
// Find the IG before current loop and clear the IGF_LOOP_ALIGN flag
4897+
if (!alignCurrentLoop && (alignInstr->idaIG->igNext == dstIG))
4898+
{
4899+
assert(!markedCurrLoop);
4900+
alignInstr->idaIG->igFlags &= ~IGF_LOOP_ALIGN;
4901+
markedCurrLoop = true;
4902+
JITDUMP("** Skip alignment for current loop IG%02u ~ IG%02u because it encloses an aligned loop "
4903+
"IG%02u ~ IG%02u.\n",
4904+
currLoopStart, currLoopEnd, emitLastLoopStart, emitLastLoopEnd);
4905+
}
4906+
4907+
// Find the IG before the last loop and clear the IGF_LOOP_ALIGN flag
4908+
if (!alignLastLoop && (alignInstr->idaIG->igNext != nullptr) &&
4909+
(alignInstr->idaIG->igNext->igNum == emitLastLoopStart))
4910+
{
4911+
assert(!markedLastLoop);
4912+
assert(alignInstr->idaIG->isLoopAlign());
4913+
alignInstr->idaIG->igFlags &= ~IGF_LOOP_ALIGN;
4914+
markedLastLoop = true;
4915+
JITDUMP("** Skip alignment for aligned loop IG%02u ~ IG%02u because it encloses the current loop "
4916+
"IG%02u ~ IG%02u.\n",
4917+
emitLastLoopStart, emitLastLoopEnd, currLoopStart, currLoopEnd);
4918+
}
4919+
4920+
if (markedLastLoop && markedCurrLoop)
4921+
{
4922+
break;
4923+
}
4924+
4925+
alignInstr = alignInstr->idaNext;
48704926
}
48714927

4872-
JITDUMP(
4873-
"** Skip alignment for loop IG%02u ~ IG%02u, because it encloses an aligned loop IG%02u ~ IG%02u.\n",
4874-
currLoopStart, currLoopEnd, emitLastInnerLoopStartIgNum, emitLastInnerLoopEndIgNum);
4928+
assert(markedLastLoop && markedCurrLoop);
48754929
}
48764930
}
48774931
}

src/coreclr/jit/emit.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,12 +1762,12 @@ class emitter
17621762
void emitJumpDistBind(); // Bind all the local jumps in method
17631763

17641764
#if FEATURE_LOOP_ALIGN
1765-
instrDescAlign* emitCurIGAlignList; // list of align instructions in current IG
1766-
unsigned emitLastInnerLoopStartIgNum; // Start IG of last inner loop
1767-
unsigned emitLastInnerLoopEndIgNum; // End IG of last inner loop
1768-
unsigned emitLastAlignedIgNum; // last IG that has align instruction
1769-
instrDescAlign* emitAlignList; // list of local align instructions in method
1770-
instrDescAlign* emitAlignLast; // last align instruction in method
1765+
instrDescAlign* emitCurIGAlignList; // list of align instructions in current IG
1766+
unsigned emitLastLoopStart; // Start IG of last inner loop
1767+
unsigned emitLastLoopEnd; // End IG of last inner loop
1768+
unsigned emitLastAlignedIgNum; // last IG that has align instruction
1769+
instrDescAlign* emitAlignList; // list of local align instructions in method
1770+
instrDescAlign* emitAlignLast; // last align instruction in method
17711771
unsigned getLoopSize(insGroup* igLoopHeader,
17721772
unsigned maxLoopSize DEBUG_ARG(bool isAlignAdjusted)); // Get the smallest loop size
17731773
void emitLoopAlignment();

0 commit comments

Comments
 (0)