-
Notifications
You must be signed in to change notification settings - Fork 5.5k
JIT: morph blocks in RPO #94247
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
JIT: morph blocks in RPO #94247
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7472,7 +7472,6 @@ void Compiler::fgMorphRecursiveFastTailCallIntoLoop(BasicBlock* block, GenTreeCa | |
| //------------------------------------------------------------------------------ | ||
| // fgAssignRecursiveCallArgToCallerParam : Assign argument to a recursive call to the corresponding caller parameter. | ||
| // | ||
| // | ||
| // Arguments: | ||
| // arg - argument to assign | ||
| // late - whether to use early or late arg | ||
|
|
@@ -13892,13 +13891,70 @@ PhaseStatus Compiler::fgMorphBlocks() | |
|
|
||
| // Morph all blocks. | ||
| // | ||
| // Note morph can add blocks downstream from the current block, | ||
| // and alter (but not null out) the current block's bbNext; | ||
| // this iterator ensures they all get visited. | ||
| // | ||
| for (BasicBlock* block : Blocks()) | ||
| if (!optLocalAssertionProp) | ||
| { | ||
| fgMorphBlock(block); | ||
| // If we aren't optimizing, we just morph in normal bbNext order. | ||
| // | ||
| // Note morph can add blocks downstream from the current block, | ||
| // and alter (but not null out) the current block's bbNext; | ||
| // this iterator ensures they all get visited. | ||
| // | ||
| for (BasicBlock* block : Blocks()) | ||
| { | ||
| fgMorphBlock(block); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // We are optimizing. Process in RPO. | ||
| // | ||
| fgRenumberBlocks(); | ||
| EnsureBasicBlockEpoch(); | ||
| fgComputeEnterBlocksSet(); | ||
| fgDfsReversePostorder(); | ||
|
|
||
| // Disallow general creation of new blocks or edges as it | ||
| // would invalidate RPO. | ||
| // | ||
| // Removal of edges, or altering dup counts, is OK. | ||
| // | ||
| INDEBUG(fgSafeBasicBlockCreation = false;); | ||
| INDEBUG(fgSafeFlowEdgeCreation = false;); | ||
|
|
||
| // Allow edge creation to genReturnBB (target of return merging) | ||
| // and the scratch block successor (target for tail call to loop). | ||
| // This will also disallow dataflow into these blocks. | ||
| // | ||
| if (genReturnBB != nullptr) | ||
| { | ||
| genReturnBB->bbFlags |= BBF_CAN_ADD_PRED; | ||
| } | ||
| if (fgFirstBBisScratch()) | ||
| { | ||
| fgFirstBB->Next()->bbFlags |= BBF_CAN_ADD_PRED; | ||
| } | ||
|
|
||
|
Comment on lines
+13924
to
+13936
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's unfortunate we need these special cases (and the new block flag), but I understand you tried to avoid it and this is a compromise. |
||
| unsigned const bbNumMax = fgBBNumMax; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you capture
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this is a vestige of my earlier versions where the number of blocks could change, before I removed all the bits that create new blocks. You think this should have If so, sure. I can add that in my next PR.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Right. That would clarify the assumption that the set of blocks doesn't change across this loop. |
||
| for (unsigned i = 1; i <= bbNumMax; i++) | ||
| { | ||
| BasicBlock* const block = fgBBReversePostorder[i]; | ||
| fgMorphBlock(block); | ||
| } | ||
|
|
||
| // Re-enable block and edge creation, and revoke | ||
| // special treatment of genReturnBB and the "first" bb | ||
| // | ||
| INDEBUG(fgSafeBasicBlockCreation = true;); | ||
| INDEBUG(fgSafeFlowEdgeCreation = true;); | ||
|
|
||
| if (genReturnBB != nullptr) | ||
| { | ||
| genReturnBB->bbFlags &= ~BBF_CAN_ADD_PRED; | ||
| } | ||
| if (fgFirstBBisScratch()) | ||
| { | ||
| fgFirstBB->Next()->bbFlags &= ~BBF_CAN_ADD_PRED; | ||
| } | ||
| } | ||
|
|
||
| // Under OSR, we no longer need to specially protect the original method entry | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How much of the cost comes from having to do the above setup calls before even computing the order?
When I've tried to compute the order before it wasn't clear to me why I would need to renumber blocks to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can grab a new profile, but the old one is probably pretty accurate: see #86822 (comment)
Renumbering likely isn't needed and not renumbering should save a bit of TP. So let me try that.
Also looking back at that early PR reminded me that I should take a look at if SSA's topological sort, it might be more efficient.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also possible we can make
DfsBlockEntrycheaper in the same way as #86839 (even thoughGetSucclooks cheap, it would probably still help a bit).It also confuses me a bit that we have multiple notions of start nodes with
fgEnterBlksandfgDomFindStartNodes. I assume the nodes found exclusively byfgDomFindStartNodesare unreachable (?) so ideally we would get rid of them earlier, but even if not, isn't it optimizable by usingbbRefs? If not, then I think usingVisitRegularSuccswould be more efficient.Anyway, don't feel the need to address it in this PR -- but might be a couple of avenues of future cleanup/improvements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like for now at least renumbering is needed. Let me add some notes to #93246 about making all this more efficient. I'll come back to that after I get the assertion prop part working.