Skip to content

Commit 46046a3

Browse files
JIT: Propagate GC safe point flag in fgSplitBlockAtBeginning (#116718)
Fixes #116704. From that failure in particular, we have the following flowgraph before loop inversion runs: ``` --------------------------------------------------------------------------------------------------------------------------------------------------------------------- BBnum BBid ref try hnd preds weight [IL range] [jump] [EH region] [flags] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- BB01 [0000] 1 1 [000..004)-> BB03(0.5),BB02(0.5) ( cond ) i BB02 [0001] 1 BB01 1 [004..005) (return) i BB03 [0002] 1 BB01 1 [005..04E)-> BB05(1) (always) i hascall gcsafe newobj BB04 [0003] 1 BB05 1 [04E..063)-> BB05(1) (always) i hascall gcsafe idxlen bwd bwd-target BB05 [0004] 2 BB03,BB04 1 [063..06A)-> BB04(0.5),BB06(0.5) ( cond ) i bwd bwd-src BB06 [0005] 1 BB05 1 [06A..0B9) (throw ) i hascall gcsafe newobj --------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` `BB06` has a tail call, and is flagged as having a GC safe point. It is also the exit block of a loop headed by `BB05`. Loop inversion gives `BB06` an empty predecessor to keep the loop canonical by calling `fgSplitBlockAtBeginning`. This calls `fgSplitBlockAtEnd`, which removes the safe point flag on the new block since it initially keeps the code in the predecessor. `fgSplitBlockAtBeginning` does not reset the flag after moving the code into the new successor. Thus, we end up with the following flowgraph: ``` --------------------------------------------------------------------------------------------------------------------------------------------------------------------- BBnum BBid ref try hnd preds weight [IL range] [jump] [EH region] [flags] --------------------------------------------------------------------------------------------------------------------------------------------------------------------- BB01 [0000] 1 1 [000..004)-> BB03(0.5),BB02(0.5) ( cond ) i BB02 [0001] 1 BB01 1 [004..005) (return) i BB03 [0002] 1 BB01 1 [005..04E)-> BB09(0.5),BB08(0.5) ( cond ) i hascall gcsafe newobj BB08 [0021] 1 BB03 1 [???..???)-> BB04(1) (always) i hascall newobj BB04 [0003] 2 BB04,BB08 1 [04E..06A)-> BB04(0.5),BB06(0.5) ( cond ) i hascall gcsafe idxlen bwd bwd-target BB06 [0005] 1 BB04 1 [???..???)-> BB09(1) (always) i hascall gcsafe newobj BB09 [0022] 2 BB03,BB06 1 [06A..0B9) (throw ) i hascall newobj --------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` Note the presence of the flag on `BB06`, which has no IR, and the lack of the flag on `BB09`, which contains the actual tail call.
1 parent 300eba1 commit 46046a3

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

src/coreclr/jit/fgbasic.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4922,6 +4922,12 @@ BasicBlock* Compiler::fgSplitBlockAtBeginning(BasicBlock* curr)
49224922
curr->bbCodeOffs = BAD_IL_OFFSET;
49234923
curr->bbCodeOffsEnd = BAD_IL_OFFSET;
49244924

4925+
// fgSplitBlockAtEnd conservatively removes the BBF_GC_SAFE_POINT flag from the new block.
4926+
// Since we moved all of the code back into the new block, set the flag again, if applicable.
4927+
// For the same reason as fgSplitBlockAtEnd, we will conservatively remove the flag from 'curr'.
4928+
newBlock->CopyFlags(curr, BBF_GC_SAFE_POINT);
4929+
curr->RemoveFlags(BBF_GC_SAFE_POINT);
4930+
49254931
return newBlock;
49264932
}
49274933

0 commit comments

Comments
 (0)