LateLowerGCFrame: Fix GC rooting for stores through select/phi of allocas#61229
Merged
LateLowerGCFrame: Fix GC rooting for stores through select/phi of allocas#61229
Conversation
…ocas
LLVM's SROA/InstCombine can merge two conditional alloca stores into a
select (or phi) over the alloca pointers:
%. = select i1 %cond, ptr %alloca1, ptr %alloca2
store ptr addrspace(10) %gc_val, ptr %.
In MaybeTrackStore, stripInBoundsOffsets() returns the select (not an
alloca), so dyn_cast<AllocaInst> fails and the function returns early
via the `else { return; }` branch. Neither alloca gets added to
ArrayAllocas, no GC frame is created, and tracked values go unrooted,
leading to GC corruption.
This commit fixes two issues:
1. Rename FindSretAllocas to FindAllocaBases and reuse it in
MaybeTrackStore to look through selects/phis when resolving the
store target to its underlying alloca(s).
2. Fix the safepoint check in runOnFunction that was skipping GC frame
creation when ArrayAllocas/TrackedStores had entries but no numbered
def existed before the safepoint in the entry block. This was a
pre-existing bug where even a simple `alloca ptr addrspace(10)` in an
entry-block-only function would fail to get rooted.
Fixes #60985
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SmallSetVector worklist removed elements from the set on pop_back_val(), allowing cyclic PHI graphs to re-insert and re-process the same values indefinitely. Use a separate SmallPtrSet to track visited values that persists across iterations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
vtjnash
reviewed
Mar 4, 2026
Instead of the overzealous HasAnySafepoint check (which checked for any safepoint anywhere in the function), have MaybeTrackStore return whether it tracked an alloca and set FirstSafepointAfterFirstDef at the call site. This integrates tracked stores into the existing def/safepoint analysis, so GC frames are only created when a safepoint actually follows the store in program order. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
selectorphibetween two alloca pointers (Repeatable GC corruption on v1.13-beta2 #60985)FindSretAllocastoFindAllocaBasesand reuse it inMaybeTrackStoreto look through selects/phis to find alloca basesrunOnFunctionthat skipped GC frame creation whenArrayAllocas/TrackedStoreshad entries but no numbered def existed before the safepoint in the entry blockDetails
LLVM's SROA/InstCombine can merge two conditional alloca stores into a
selectover the alloca pointers:In
MaybeTrackStore,stripInBoundsOffsets()returns the select (not an alloca), sodyn_cast<AllocaInst>fails and the function returns early. Neither alloca gets added toArrayAllocas, no GC frame is created, and tracked values go unrooted → GC corruption.The fix also addresses a pre-existing issue where the safepoint check in
runOnFunctionwould skip GC frame creation whenArrayAllocashad entries but no numbered def existed before the safepoint in the entry block.Test plan
test/llvmpasses/late-lower-gc-select-store.llwith regression tests for both select and phi caseslate-lower-gc*.llFileCheck tests still passclang-tidy,clang-sa,clang-sagc) with no issues🤖 Generated with Claude Code