Skip to content

JIT: Remove BBF_NEEDS_GCPOLL and BBF_HAS_SUPPRESSGC_CALL#129153

Closed
EgorBo wants to merge 1 commit into
dotnet:mainfrom
EgorBo:egorbo/remove-gcpoll-block-flags
Closed

JIT: Remove BBF_NEEDS_GCPOLL and BBF_HAS_SUPPRESSGC_CALL#129153
EgorBo wants to merge 1 commit into
dotnet:mainfrom
EgorBo:egorbo/remove-gcpoll-block-flags

Conversation

@EgorBo

@EgorBo EgorBo commented Jun 9, 2026

Copy link
Copy Markdown
Member

Removes the per-basic-block flags BBF_NEEDS_GCPOLL and BBF_HAS_SUPPRESSGC_CALL. The GC-poll insertion phase (fgInsertGCPolls) now relies on the method-global OMF_NEEDS_GCPOLLS flag to decide whether to run, and performs the full tree walk (blockNeedsGCPoll) in both tier0 (minopts) and tier1 (optimized). Previously tier0 relied on the per-block flags and only tier1 did the walk.

The walk recognizes every case the per-block flags used to track:

  • SuppressGCTransition unmanaged calls (was BBF_HAS_SUPPRESSGC_CALL)
  • GT_GCPOLL nodes from Thread.FastPollGC (was BBF_NEEDS_GCPOLL)
  • slow tail calls dispatched via the JIT helper (x86-only), detected via IsTailCallViaJitHelper() (was BBF_NEEDS_GCPOLL)

This drops the need to keep these per-block flags in sync across block splits/compaction. As a side effect it removes a redundant GC poll that BBF_NEEDS_GCPOLL could produce when it propagated (via BBF_SPLIT_GAINED/BBF_COMPACT_UPD) to both halves of a split FastPollGC block.

Validation

SuperPMI asmdiffs (Checked):

  • x64 (2.58M contexts: 961K MinOpts + 1.62M FullOpts): 0 regressions, −5,957 bytes.
  • x86 (exercises the tail-call-via-helper path): 0 regressions, 0 new asserts.

All diffs are the FastPollGC redundant-poll dedup in Array.Copy/CopyImpl/Queue.Grow. Verified by disassembly that the essential poll after the no-GC bulk-move FCALL is preserved; only the extra poll (previously caused by BBF_NEEDS_GCPOLL propagating across a block split) is removed.

Note

This pull request (code and description) was generated with the assistance of GitHub Copilot.

The GC poll insertion phase (fgInsertGCPolls) now relies solely on the
method-global OMF_NEEDS_GCPOLLS flag to decide whether to run, and performs
the full tree walk (blockNeedsGCPoll) in both tier0 (minopts) and tier1
(optimized) to find the blocks that need a poll. Previously tier0 relied on
the per-block BBF_HAS_SUPPRESSGC_CALL / BBF_NEEDS_GCPOLL flags while only
tier1 did the walk.

The walk recognizes every case the per-block flags used to track:

* SuppressGCTransition unmanaged calls (was BBF_HAS_SUPPRESSGC_CALL)
* GT_GCPOLL nodes from Thread.FastPollGC (was BBF_NEEDS_GCPOLL)
* slow tail calls dispatched via the JIT helper, x86-only, detected via
  IsTailCallViaJitHelper() (was BBF_NEEDS_GCPOLL)

This drops the need to keep these per-block flags in sync across block
splits/compaction. As a side effect it removes a redundant GC poll that
BBF_NEEDS_GCPOLL could produce when it propagated (via BBF_SPLIT_GAINED /
BBF_COMPACT_UPD) to both halves of a split FastPollGC block.

Validated with SuperPMI asmdiffs on x64 (2.58M contexts) and x86: no
regressions; the only diffs are the FastPollGC redundant-poll dedup in
Array.Copy/CopyImpl/Queue.Grow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 9, 2026 03:31
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jun 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the per-basic-block flags BBF_NEEDS_GCPOLL and BBF_HAS_SUPPRESSGC_CALL and updates GC-poll insertion (fgInsertGCPolls) to rely on the method-global OMF_NEEDS_GCPOLLS gate plus per-block tree walks to detect blocks requiring a GC poll.

Changes:

  • Remove BBF_NEEDS_GCPOLL / BBF_HAS_SUPPRESSGC_CALL and stop propagating them across block splits/compaction.
  • Update importer/morph to set only OMF_NEEDS_GCPOLLS for Thread.FastPollGC, SuppressGCTransition unmanaged calls, and tailcall-via-JIT-helper cases.
  • Make fgInsertGCPolls scan trees in both minopts and optimized builds, and add detection for tail calls dispatched via the JIT helper.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/coreclr/jit/morph.cpp Stops setting per-block poll flags; sets OMF_NEEDS_GCPOLLS for relevant constructs and updates comments/logging.
src/coreclr/jit/importercalls.cpp Removes BBF_NEEDS_GCPOLL marking for Thread.FastPollGC; relies on GT_GCPOLL + OMF_NEEDS_GCPOLLS.
src/coreclr/jit/flowgraph.cpp Makes fgInsertGCPolls always use tree scanning; adds tailcall-via-helper detection and replaces per-block-flag checks.
src/coreclr/jit/block.h Deletes the two basic-block flags and removes them from flag-propagation sets.
src/coreclr/jit/block.cpp Removes debug display strings for the deleted flags.

Comment on lines +51 to +55
else if (call->IsTailCallViaJitHelper())
{
// Slow tail calls dispatched via the JIT helper do not return, so the
// helper itself cannot poll for GC. We need to insert a poll before it.
blockMayNeedGCPoll = true;
Comment on lines +82 to +98
static bool blockHasTailCallViaHelper(BasicBlock* block)
{
for (Statement* const stmt : block->NonPhiStatements())
{
if ((stmt->GetRootNode()->gtFlags & GTF_CALL) != 0)
{
for (GenTree* const tree : stmt->TreeList())
{
if (tree->OperIs(GT_CALL) && tree->AsCall()->IsTailCallViaJitHelper())
{
return true;
}
}
}
}
return false;
}
@EgorBo EgorBo closed this Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants