Skip to content

Skip phis with no incoming values when placing a nulled shadow - #3127

Open
ZuseZ4 wants to merge 1 commit into
EnzymeAD:mainfrom
ZuseZ4:fix-e11-proper
Open

Skip phis with no incoming values when placing a nulled shadow#3127
ZuseZ4 wants to merge 1 commit into
EnzymeAD:mainfrom
ZuseZ4:fix-e11-proper

Conversation

@ZuseZ4

@ZuseZ4 ZuseZ4 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

When invertPointerM nulls the shadow of a partially-float constant it inserts an alloca, a store of the primal and the per-byte zeroing just after the value's clone, walking past any following phis so the stores do not land in the phi region. That walk stopped at a phi with no incoming values.

The PHINode case of this same function creates its shadow phi with CreatePHI(shadowTy, phi->getNumIncomingValues()) and only calls addIncoming after it has recursed into invertPointerM for each incoming value. So while that recursion runs, the shadow phi genuinely has zero incoming values, the walk stops on it, and the stores are inserted above it.

That leaves the block's phis no longer contiguous at its start, and the resulting function is rejected:

Instruction does not dominate all uses!
PHI nodes not grouped at top of basic block!
function failed verification

Both complaints come from the single misplacement: the cache store for the primal phi is subsequently emitted at getFirstNonPHI(), which by then precedes that phi's definition.

The incoming count says nothing about whether a phi is in the phi region, so skip every phi.

fixes: #3029
closes: #3126

cc @wsmoses

When invertPointerM nulls the shadow of a partially-float constant it inserts an
alloca, a store of the primal and the per-byte zeroing just after the value's
clone, walking past any following phis so the stores do not land in the phi
region. That walk stopped at a phi with no incoming values.

The PHINode case of this same function creates its shadow phi with
CreatePHI(shadowTy, phi->getNumIncomingValues()) and only calls addIncoming
after it has recursed into invertPointerM for each incoming value. So while that
recursion runs, the shadow phi genuinely has zero incoming values, the walk
stops on it, and the stores are inserted above it.

That leaves the block's phis no longer contiguous at its start, and the
resulting function is rejected:

  Instruction does not dominate all uses!
  PHI nodes not grouped at top of basic block!
  function failed verification

Both complaints come from the single misplacement: the cache store for the
primal phi is subsequently emitted at getFirstNonPHI(), which by then precedes
that phi's definition.

The incoming count says nothing about whether a phi is in the phi region, so
skip every phi.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PHI nodes not grouped at top of basic block

1 participant