-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Remove CHK_FLOW_UPDATE stress mode #122970
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: jakobbotsch <[email protected]>
| void Compiler::fgDebugCheckUpdate() | ||
| { | ||
| if (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30)) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| /* We check for these conditions: | ||
| * no unreachable blocks -> no blocks have countOfInEdges() = 0 | ||
| * no empty blocks -> !block->isEmpty(), unless non-removable or multiple in-edges | ||
| * no un-imported blocks -> no blocks have BBF_IMPORTED not set (this is | ||
| * kind of redundant with the above, but to make sure) | ||
| * no un-compacted blocks -> BBJ_ALWAYS with jump to block with no other jumps to it (countOfInEdges() = 1) | ||
| */ | ||
|
|
||
| BasicBlock* prev; | ||
| BasicBlock* block; | ||
| for (prev = nullptr, block = fgFirstBB; block != nullptr; prev = block, block = block->Next()) | ||
| { | ||
| /* no unreachable blocks */ | ||
|
|
||
| if ((block->countOfInEdges() == 0) && !block->HasFlag(BBF_DONT_REMOVE)) | ||
| { | ||
| noway_assert(!"Unreachable block not removed!"); | ||
| } | ||
|
|
||
| /* no empty blocks */ | ||
|
|
||
| if (block->isEmpty() && !block->HasFlag(BBF_DONT_REMOVE)) | ||
| { | ||
| switch (block->GetKind()) | ||
| { | ||
| case BBJ_CALLFINALLY: | ||
| case BBJ_EHFINALLYRET: | ||
| case BBJ_EHFAULTRET: | ||
| case BBJ_EHFILTERRET: | ||
| case BBJ_RETURN: | ||
| /* for BBJ_ALWAYS is probably just a GOTO, but will have to be treated */ | ||
| case BBJ_ALWAYS: | ||
| case BBJ_EHCATCHRET: | ||
| /* These jump kinds are allowed to have empty tree lists */ | ||
| break; | ||
|
|
||
| default: | ||
| /* it may be the case that the block had more than one reference to it | ||
| * so we couldn't remove it */ | ||
|
|
||
| if (block->countOfInEdges() == 0) | ||
| { | ||
| noway_assert(!"Empty block not removed!"); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| /* no un-imported blocks */ | ||
|
|
||
| if (!block->HasFlag(BBF_IMPORTED)) | ||
| { | ||
| /* internal blocks do not count */ | ||
|
|
||
| if (!block->HasFlag(BBF_INTERNAL)) | ||
| { | ||
| noway_assert(!"Non IMPORTED block not removed!"); | ||
| } | ||
| } | ||
|
|
||
| // Check for an unnecessary jumps to the next block. | ||
| // A conditional branch should never jump to the next block as it can be folded into a BBJ_ALWAYS. | ||
| if (block->KindIs(BBJ_COND) && block->TrueEdgeIs(block->GetFalseEdge())) | ||
| { | ||
| noway_assert(!"Unnecessary jump to the next block!"); | ||
| } | ||
|
|
||
| // For a BBJ_CALLFINALLY block we make sure that we are followed by a BBJ_CALLFINALLYRET block | ||
| // or that it's a BBF_RETLESS_CALL. | ||
| if (block->KindIs(BBJ_CALLFINALLY)) | ||
| { | ||
| assert(block->HasFlag(BBF_RETLESS_CALL) || block->isBBCallFinallyPair()); | ||
| } | ||
|
|
||
| /* no un-compacted blocks */ | ||
|
|
||
| if (fgCanCompactBlock(block)) | ||
| { | ||
| noway_assert(!"Found un-compacted blocks!"); | ||
| } | ||
| } | ||
| } |
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.
@copilot Keep the fgDebugCheckUpdate function, but remove the STRESS_CHK_FLOW_UPDATE check, i.e. we can always run the code in debug.
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.
@copilot Revert this change, remove only the STRESS_CHK_FLOW_UPDATE check
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.
Done in 54e6058. The fgDebugCheckUpdate function now runs unconditionally in all debug builds.
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.
The changes are already correct in 54e6058. Only the STRESS_CHK_FLOW_UPDATE definition and stress check have been removed - the fgDebugCheckUpdate() function, its declaration, and call site remain intact.
Per feedback from @jakobbotsch, the fgDebugCheckUpdate function is now always executed in debug builds instead of being gated by the STRESS_CHK_FLOW_UPDATE stress mode. Co-authored-by: jakobbotsch <[email protected]>
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Remove CHK_FLOW_UPDATE stress mode
STRESS_MODE(CHK_FLOW_UPDATE)from compiler.hfgDebugCheckUpdate()functionfgDebugCheckUpdate()function to run always in debug buildsfgDebugCheckUpdate()in fgopt.cppSummary
Removed the CHK_FLOW_UPDATE stress mode. The
fgDebugCheckUpdate()function now runs unconditionally in all debug builds instead of being gated by the stress mode. This provides better flow graph validation coverage during development.Changes Made:
STRESS_MODE(CHK_FLOW_UPDATE)from the stress modes enumeration incompiler.hif (!compStressCompile(STRESS_CHK_FLOW_UPDATE, 30))check fromfgDebugCheckUpdate()infgdiagnostic.cppThe function continues to validate flow graph invariants including no unreachable blocks, empty blocks, un-imported blocks, un-compacted blocks, unnecessary jumps, and proper BBJ_CALLFINALLY block structure.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.