You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Test failure JIT/Performance/CodeQuality/Benchstones/BenchF/MatInv4/MatInv4/MatInv4.sh #61899
This is happening precisely because of a scenario for which I added a separate flag to track if alignment flag is removed or not. But after re-thinking from #60787 (comment) I decided to remove it. Here is the scenario:
We align a loop IG04 that sometimes might contain a jmp instruction that we selected to hide the align instruction for a future loop (IG15 in this case). When we calculate the loop adjustments heuristic, we get the loop size of loop that starts at IG04. We see that IG05 contains align instruction at the end, but since we don't know yet how much padding will be added at the end of IG05, we exclude the 15 bytes padding bytes from the loop size. However, later, when we have to adjust the alignment for the loop that starts at IG15, we might decide to either not add padding at all (because of heuristics) or might add padding <= 15 bytes to it. As such the size of a loop that starts at IG04 will vary compared to the size we calculated our alignment heuristics. As such the presence of a IG that ends with alignment (align behind jmp) is misleading to our calculation and IMO, we should not align such a loop (IG04 in below example).
...IG03: <align for IG04>IG04: ; loop start at IG04 ...IG05: ...jmp ... <align for IG15> ; there is another loop at IG15 and we decide to put its alignment in this block.IG06: ...jne IG04...
Alternatively, one may argue to why bother place align instruction for loop IG15 at the end of IG05 (which is part of a loop) rather than placing it in IG14 which is just before the loop start. We cannot do it currently because during placeLoopAlignInstructions phase, we do not have information of which BasicBlock is part of a loop. I will discuss this offline with @BruceForstall as well before going forward with this approach.
IIUC, the assert happens because when we go to emit the alignment for IG04, we calculate the alignment padding needed by calling emitCalculatePaddingForLoopAlignment, which involves calculating the loop size of the loop starting at IG04. But if we had previously decided not to align IG15, the align instruction in IG05 would get zeroed (in size), and therefore our original estimate for loop size and final estimate for loop size will differ, which might change our decision about adding padding in IG03 at all?
Is the assert valid? It seems like we might not be able to guarantee loop size.
Or, should emitCalculatePaddingForLoopAlignment not include any alignment instruction sizes in the loop size estimate? (It might underestimate actual loop size, which might lead to more loop alignment, but then again, these embedded alignment NOP instructions shouldn't get executed.)
But if we had previously decided not to align IG15, the align instruction in IG05 would get zeroed (in size),
If we decide not to align IG15, that is best case scenario because we excluded the padding bytes from our loop size calculation of loop that starts at IG03. However, the problem comes when we decide to align IG15 and hence add padding of XXX bytes. In such case, the IG03 loop size is guarantee to be more by XXX bytes than we originally calculated.
which might change our decision about adding padding in IG03 at all?
That's right.
Is the assert valid? It seems like we might not be able to guarantee loop size.
The assert is not valid only in two scenarios:
If we are adding the padding behind a jmp for some future loop that doesn't immediately follow the current IG. We already account for that:
For loops that contains a jmp and we decide to hide align behind that jmp which this issue is about. I am proposing to not align such loops and hence we will never be adding padding for such loops.
Or, should emitCalculatePaddingForLoopAlignment not include any alignment instruction sizes in the loop size estimate?
Spoke offline with @BruceForstall and here are few things we concluded:
Use bbNaturalLoopNum in placement phase to determine whether to put align in the block that is part of loop
Move the loop intersection detection logic from IG-based to BB-based inside placement phase. For this to happen, we might have to do the block renumbering once again before the placement phase (do in follow-up PR).
I also realized that I was handling the case to add align behind jmp only for IGs that comes after processing the current loop that needs alignment, but it got lost when I added the placement phase.
Activity
JulieLeeMSFT commentedon Nov 22, 2021
@BruceForstall PTAL.
BruceForstall commentedon Nov 24, 2021
@kunalspathak assert related to loop alignment (and also JitStressRegs=1?)
kunalspathak commentedon Nov 28, 2021
This is happening precisely because of a scenario for which I added a separate flag to track if alignment flag is removed or not. But after re-thinking from #60787 (comment) I decided to remove it. Here is the scenario:
We align a loop
IG04that sometimes might contain ajmpinstruction that we selected to hide thealigninstruction for a future loop (IG15in this case). When we calculate the loop adjustments heuristic, we get the loop size of loop that starts atIG04. We see thatIG05containsaligninstruction at the end, but since we don't know yet how much padding will be added at the end ofIG05, we exclude the 15 bytes padding bytes from the loop size. However, later, when we have to adjust the alignment for the loop that starts atIG15, we might decide to either not add padding at all (because of heuristics) or might add padding <= 15 bytes to it. As such the size of a loop that starts atIG04will vary compared to the size we calculated our alignment heuristics. As such the presence of a IG that ends with alignment (alignbehindjmp) is misleading to our calculation and IMO, we should not align such a loop (IG04in below example).Alternatively, one may argue to why bother place
aligninstruction for loopIG15at the end ofIG05(which is part of a loop) rather than placing it inIG14which is just before the loop start. We cannot do it currently because duringplaceLoopAlignInstructionsphase, we do not have information of whichBasicBlockis part of a loop. I will discuss this offline with @BruceForstall as well before going forward with this approach.BruceForstall commentedon Nov 30, 2021
IIUC, the assert happens because when we go to emit the alignment for IG04, we calculate the alignment padding needed by calling
emitCalculatePaddingForLoopAlignment, which involves calculating the loop size of the loop starting at IG04. But if we had previously decided not to align IG15, the align instruction in IG05 would get zeroed (in size), and therefore our original estimate for loop size and final estimate for loop size will differ, which might change our decision about adding padding in IG03 at all?Is the assert valid? It seems like we might not be able to guarantee loop size.
Or, should
emitCalculatePaddingForLoopAlignmentnot include any alignment instruction sizes in the loop size estimate? (It might underestimate actual loop size, which might lead to more loop alignment, but then again, these embedded alignment NOP instructions shouldn't get executed.)kunalspathak commentedon Nov 30, 2021
If we decide not to align
IG15, that is best case scenario because we excluded the padding bytes from our loop size calculation of loop that starts atIG03. However, the problem comes when we decide to alignIG15and hence add padding of XXX bytes. In such case, theIG03loop size is guarantee to be more by XXX bytes than we originally calculated.That's right.
The assert is not valid only in two scenarios:
jmpfor some future loop that doesn't immediately follow the current IG. We already account for that:runtime/src/coreclr/jit/emitxarch.cpp
Lines 10037 to 10040 in 85642f8
I am improving that check further in #62106.
jmpand we decide to hidealignbehind thatjmpwhich this issue is about. I am proposing to not align such loops and hence we will never be adding padding for such loops.We already do that today:
runtime/src/coreclr/jit/emit.cpp
Lines 5127 to 5128 in 85642f8
kunalspathak commentedon Dec 1, 2021
Spoke offline with @BruceForstall and here are few things we concluded:
bbNaturalLoopNumin placement phase to determine whether to putalignin the block that is part of loopkunalspathak commentedon Dec 1, 2021
I also realized that I was handling the case to add
alignbehindjmponly for IGs that comes after processing the current loop that needs alignment, but it got lost when I added the placement phase.fix for dotnet#61899
Revert "fix for dotnet#61899"
VincentBu commentedon Dec 6, 2021
Failed again in: runtime-coreclr jitstressregs 20211205.1
Failed test:
Error message:
Filter blocks to be used for hiding alignment instruction (#62262)
kunalspathak commentedon Dec 11, 2021
This is fixed in #62262