Uh oh!
There was an error while loading. Please reload this page.
JIT: Simplify if-conversion - #125347
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
* simplify IfConvertCheckStmts * small things
9792586 to
5c1616cCompareThere was a problem hiding this comment.
Pull request overview
This PR simplifies the CoreCLR JIT if-conversion implementation by collapsing the prior multi-block flow search into a single, direct-flow check, under the assumption that Then/Else paths do not contain empty/chained blocks.
Changes:
- Replace the prior bounded “walk” of Then/Else chains with a single
IfConvertCheckFlow()check. - Simplify statement validation to operate on a single block (ignoring NOPs) rather than scanning a block chain to
m_finalBlock. - Simplify debug dumping and block removal to target only the identified Then/Else blocks.
Uh oh!
There was an error while loading. Please reload this page.
@a74nh@jakobbotsch What do you think? I guess the main question is whether this is a reasonable assumption to make in the first place: assert(m_startBlock->GetFalseTarget()->GetUniqueSucc() == m_finalBlock);
if (m_doElseConversion)
{
assert(m_startBlock->GetTrueTarget()->GetUniqueSucc() == m_finalBlock);
}Meaning no flow through empty blocks inside Then/Else cases. I simplified:
|
a74nh
commented
Mar 13, 2026
The original assumption was that the graph potentially could contain multiple blocks with a straight line flow between them. What could give that scenario?
Even if it's not a 100% correct assumption, sounds like we're still catching everything of relevance with your change. |
BoyBaykiller
commented
Mar 14, 2026
Do you mean something like this. Because it does get recognized. We just bail on profitability for the outer one: inta74nh(boolx,booly){if(x){if(y){return1;}else{return2;}}else{return3;}}moveax,3movecx,2movr10d,1testr8b,r8b cmovne ecx,r10dtestdl,dl cmovne eax,ecx ;; size=28 bbWeight=1 PerfScore 1.75G_M25408_IG03: ;; offset=0x001CretAnyway so yeah, while there will still be Then/Else cases with multiple blocks that have linear flow this PR says: "Such cases won't be amendable to if-conversion anyway so let's bail in |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
* add 'assert(m_cond->OperIsCompare())' * combine IfConvertCheckFlow + IfConvertCheckStmts into new IfConvertCheck * get m_mainOper from m_thenOperation instead of flow check
BoyBaykiller
commented
Mar 23, 2026
@a74nh does everything look ok now or are there other changes you would like me to do? |
a74nh
left a comment
There was a problem hiding this comment.
I'm happy with this now.
Although, looks like formatting needs fixing.
jakobbotsch
commented
Apr 8, 2026
@BoyBaykiller Can you address the formatting issue? |
@BoyBaykiller The jit-format job uploads a patch file when the formatting fails that you can apply locally to fix it. You can also run jit-format locally before you even commit: https://github.com/dotnet/jitutils/blob/main/doc/formatting.md |
BoyBaykiller
commented
Apr 10, 2026
Thanks. I'll know that for the future. In this case vscode formatting did the job |
Uh oh!
There was an error while loading. Please reload this page.
A Fuzzlyn-generated repro hits `assert(!block->HasFlag(BBF_DONT_REMOVE))` during the JIT's *If conversion* phase when the Then block is the start of a try region. Bisected to dea4756 (#125347), which simplified `IfConvertCheckFlow` and inadvertently dropped the `BasicBlock::sameEHRegion` check previously performed by `IfConvertCheckInnerBlockFlow`. Without it, if-conversion proceeds on a Then/Else block that begins an EH region, then trips the assert when later removing it. ## Changes - **`src/coreclr/jit/ifconversion.cpp`** — In `OptIfConversionDsc::IfConvertCheckFlow`, bail when `falseBb` (Then) or `trueBb` (Else, when present) is not in the same EH region as `m_startBlock`. After merging `origin/main`, the Else guard uses the new `HasElseBlock()` helper (which replaced the removed `m_doElseConversion` member). - **`src/tests/JIT/Regression/JitBlue/Runtime_127446/Runtime_127446.cs`** — Regression test using the original repro. The test source is added to the shared merged `src/tests/JIT/Regression/Regression_ro_2.csproj` (alongside other JitBlue regression tests); no per-test csproj or environment variables are needed. ```cpp if (falseBb->GetUniquePred(m_compiler) == nullptr) { return false; } // The Then/Else blocks will be removed by if-conversion, so they must be in the same // EH region as m_startBlock. Otherwise they may be the start of a try/handler region // (and thus marked BBF_DONT_REMOVE), or removing them could leave dangling EH state. if (!BasicBlock::sameEHRegion(falseBb, m_startBlock)) { return false; } m_finalBlock = HasElseBlock() ? trueBb->GetUniqueSucc() : trueBb; if (HasElseBlock() && !BasicBlock::sameEHRegion(trueBb, m_startBlock)) { return false; } ``` Verified the assert reproduces on the unfixed JIT and is gone with the fix; the new test passes through the merged test runner (`global::Runtime_127446.Runtime_127446.TestEntryPoint()` → Passed) after merging the latest `origin/main`. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com> Co-authored-by: jakobbotsch <7887810+jakobbotsch@users.noreply.github.com> Co-authored-by: Egor Bogatov <egorbo@gmail.com>
Zero-diff change that simplifies if-conversion based on the assumption that there are no empty blocks inside the Then and Else case. See: #125072 (comment)