Skip to content

Commit c8d6048

Browse files
authored
JIT: Improve block IL offset range selection when splitting (#121298)
In debug codegen we expect basic blocks to have valid start IL offsets, potentially to an invalid IL end offset. When we split a block at a node, we find the end offset by looking backwards from that node for an `IL_OFFSET` node. If we find such a node, we use it as the split point IL offset. Otherwise we use `BAD_IL_OFFSET` and start the next block at the end offset (making it have a 0 byte range). This latter behavior is problematic if the bottom portion of the split has its own `IL_OFFSET` nodes. In that case we can end up with `IL_OFFSET` nodes pointing outside the region of the basic block. If we later split again, then we can end up creating illegal IL offset ranges for unoptimized code. In an example case we first ended up with the bottom block having an IL offset range of `[0aa..0aa)` but still containing an `IL_OFFSET` with an offset of `092`. When we later split the bottom block again we ended up with `[0aa..0aa), [092..0aa)` and hit an assert. To address the problem change the behavior in the following way: * If we find no `IL_OFFSET` node in the upper block, then look for one in the lower block, and use its value as the split point * If we find no `IL_OFFSET` in both blocks then consider the lower block empty and the upper block to have everything (same behavior as before). * One exception to above: if the end was already `BAD_IL_OFFSET` then we have to consider the upper block to be empty as we cannot represent the other case This fixes #119616. However for that specific case, which is inside async code, we will have the exact IL offset of the async call we are splitting at after #120303, so we will be able to do better. I'll make that change as part of that PR.
1 parent 7bcfee1 commit c8d6048

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

src/coreclr/jit/fgbasic.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4840,11 +4840,34 @@ BasicBlock* Compiler::fgSplitBlockAfterNode(BasicBlock* curr, GenTree* node)
48404840
}
48414841
}
48424842

4843-
curr->bbCodeOffsEnd = max(curr->bbCodeOffs, splitPointILOffset);
4843+
if (splitPointILOffset == BAD_IL_OFFSET)
4844+
{
4845+
// Try to look forwards in the next block
4846+
for (GenTree* node : LIR::AsRange(newBlock))
4847+
{
4848+
if (node->OperIs(GT_IL_OFFSET))
4849+
{
4850+
GenTreeILOffset* ilOffset = node->AsILOffset();
4851+
DebugInfo rootDI = ilOffset->gtStmtDI.GetRoot();
4852+
if (rootDI.IsValid())
4853+
{
4854+
splitPointILOffset = rootDI.GetLocation().GetOffset();
4855+
break;
4856+
}
4857+
}
4858+
}
4859+
}
48444860

4845-
// Also use this as the beginning offset of the next block. Presumably we could/should
4846-
// look to see if the first node is a GT_IL_OFFSET node, and use that instead.
4847-
newBlock->bbCodeOffs = min(splitPointILOffset, newBlock->bbCodeOffsEnd);
4861+
if (splitPointILOffset == BAD_IL_OFFSET)
4862+
{
4863+
// If we found no IL_OFFSET in the block then we cannot do anything
4864+
// but guess. Let's make the old block (upper part) contain
4865+
// everything if we have an end, and otherwise nothing.
4866+
splitPointILOffset = curr->bbCodeOffsEnd == BAD_IL_OFFSET ? curr->bbCodeOffs : curr->bbCodeOffsEnd;
4867+
}
4868+
4869+
curr->bbCodeOffsEnd = splitPointILOffset;
4870+
newBlock->bbCodeOffs = splitPointILOffset;
48484871
}
48494872
else
48504873
{

0 commit comments

Comments
 (0)