JIT: Make BasicBlock::bbPrev and bbNext private#93032
JIT: Make BasicBlock::bbPrev and bbNext private#93032amanasifkhalid merged 15 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
|
No asm diffs but some TP diffs (maybe because SetBBPrev() does more than what it replaces?) |
|
Seems like we should work to avoid too many E.g., instead of
This might be more controversial, but Given the above, should we name Looks like there are a few more places that can use the block iterators instead of manual |
src/coreclr/jit/block.h
Outdated
| } | ||
| } | ||
|
|
||
| BasicBlock* GetBBNext() const |
There was a problem hiding this comment.
While we're renaming things, we could give these more "obvious" names, e. g. GetNextBlock.
We previously had BasicBlock::setNext() that updated bbNext, and also null-checked the new next block to see if it could update its bbPrev; most of the time, we'd just directly update bbNext, and would sparingly call setNext() if we also intended to update the next block's bbPrev. Would it make sense to not have SetBBNext() do this additional work, and keep setNext() around to do it? I think this would reduce/eliminate the TP diffs, but we'd lose the guarantee that bbNext and bbNext->bbPrev are consistent within SetBBNext().
I'm happy to add helper methods for checking bbNext/bbPrev. This is for readability, since GetBBNext() should be getting inlined, right? |
Would it be preferable to check against fgFirstBB and fgLastBB instead of adding new methods? Ditto checking if block == fgFirstColdBlock instead of a new method (though for checking if a block is the last hot block, I agree we'd need a new method to avoid calling GetBBNext()). |
No, it's probably best to leave it as you have it now.
Yes.
We don't always have a For |
|
I suspect over time we're going to see more and more cases where BB operations are contextual and need access to the compiler instance. At various times I've wondered if blocks should just point back to some parent object (either the compiler or some sort of "flow graph" object, but that seems wasteful. Given that blocks are all the same size we could perhaps play tricks to factor out common fields, if we say allocated them contiguously. For now, I think providing the context when needed via args is ok. One issue with either a context arg or a parent object is that when we inline we do some funny things as there are two compiler objects around, and so it's possible to consult the wrong one.... |
|
@BruceForstall @AndyAyersMS PTAL. CI is clean, but small TP diffs. I'm planning on making the jump target members private next; if we can assert the jump kind is valid every time we try to read the jump destination, then maybe we can remove code that sets the jump destination to null when changing the jump kind. This might make up for the TP regression in Release builds. |
BruceForstall
left a comment
There was a problem hiding this comment.
Found a few nits that could be updated. Can't say I looked at every case.
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // IsLastHotBlock: see if this is the last block before the cold section |
There was a problem hiding this comment.
Should we have a corresponding IsFirstColdBlock(Compiler*)?
There was a problem hiding this comment.
I can add that in for consistency.
src/coreclr/jit/block.h
Outdated
| assert((m_block->IsLast()) || m_block->Next()->PrevIs(m_block)); | ||
| assert((m_block->IsFirst()) || m_block->Prev()->NextIs(m_block)); |
There was a problem hiding this comment.
With the function, we can remove an unnecessary set of parens
| assert((m_block->IsLast()) || m_block->Next()->PrevIs(m_block)); | |
| assert((m_block->IsFirst()) || m_block->Prev()->NextIs(m_block)); | |
| assert(m_block->IsLast() || m_block->Next()->PrevIs(m_block)); | |
| assert(m_block->IsFirst() || m_block->Prev()->NextIs(m_block)); |
There was a problem hiding this comment.
Thanks for catching all these nits (sorry, these kinds of PRs seem especially tedious to review).
src/coreclr/jit/codegencommon.cpp
Outdated
| assert(block != nullptr); | ||
| const VARSET_TP& gcrefVarsArg(GetEmitter()->emitThisGCrefVars); | ||
| bool last = (block->bbNext == nullptr); | ||
| bool last = (block->IsLast()); |
There was a problem hiding this comment.
| bool last = (block->IsLast()); | |
| bool last = block->IsLast(); |
or just substitute it in the call below and eliminate the last var
src/coreclr/jit/codegencommon.cpp
Outdated
| JITDUMP("Reserving funclet epilog IG for block " FMT_BB "\n", block->bbNum); | ||
|
|
||
| bool last = (block->bbNext == nullptr); | ||
| bool last = (block->IsLast()); |
src/coreclr/jit/codegenlinear.cpp
Outdated
| /* Is this the last block, and are there any open scopes left ? */ | ||
|
|
||
| bool isLastBlockProcessed = (block->bbNext == nullptr); | ||
| bool isLastBlockProcessed = (block->IsLast()); |
There was a problem hiding this comment.
| bool isLastBlockProcessed = (block->IsLast()); | |
| bool isLastBlockProcessed = block->IsLast(); |
src/coreclr/jit/codegenlinear.cpp
Outdated
| if (block->isBBCallAlwaysPair()) | ||
| { | ||
| isLastBlockProcessed = (block->bbNext->bbNext == nullptr); | ||
| isLastBlockProcessed = (block->Next()->IsLast()); |
There was a problem hiding this comment.
| isLastBlockProcessed = (block->Next()->IsLast()); | |
| isLastBlockProcessed = block->Next()->IsLast(); |
src/coreclr/jit/codegenlinear.cpp
Outdated
| // if the next block is a BBJ_RETURN, an epilog will be generated, but there may be some instructions | ||
| // generated before the OS epilog starts, such as a GS cookie check. | ||
| if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext)) | ||
| if ((block->IsLast()) || !BasicBlock::sameEHRegion(block, block->Next())) |
There was a problem hiding this comment.
| if ((block->IsLast()) || !BasicBlock::sameEHRegion(block, block->Next())) | |
| if (block->IsLast() || !BasicBlock::sameEHRegion(block, block->Next())) |
src/coreclr/jit/codegenlinear.cpp
Outdated
| } | ||
|
|
||
| if ((block->bbNext != nullptr) && (block->bbNext->isLoopAlign())) | ||
| if (!block->IsLast() && (block->Next()->isLoopAlign())) |
There was a problem hiding this comment.
| if (!block->IsLast() && (block->Next()->isLoopAlign())) | |
| if (!block->IsLast() && block->Next()->isLoopAlign()) |
src/coreclr/jit/compiler.cpp
Outdated
| } | ||
|
|
||
| if ((block->bbNext != nullptr) && (block->bbNext->isLoopAlign())) | ||
| if (!block->IsLast() && (block->Next()->isLoopAlign())) |
There was a problem hiding this comment.
| if (!block->IsLast() && (block->Next()->isLoopAlign())) | |
| if (!block->IsLast() && block->Next()->isLoopAlign()) |
src/coreclr/jit/fgbasic.cpp
Outdated
| printf("Relocated block%s [" FMT_BB ".." FMT_BB "] inserted after " FMT_BB "%s\n", (bStart == bEnd) ? "" : "s", | ||
| bStart->bbNum, bEnd->bbNum, insertAfterBlk->bbNum, | ||
| (insertAfterBlk->bbNext == nullptr) ? " at the end of method" : ""); | ||
| (insertAfterBlk->IsLast()) ? " at the end of method" : ""); |
There was a problem hiding this comment.
| (insertAfterBlk->IsLast()) ? " at the end of method" : ""); | |
| insertAfterBlk->IsLast() ? " at the end of method" : ""); |
|
@BruceForstall I think I fixed all the style issues introduced (plus a couple extra I found along the way). |
Followup to #92908, and next step for #93020. CC @dotnet/jit-contrib.