Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix out-of-bounds crash in Stream affinity analysis for scf.while#24723

Open
pstarkcdpr wants to merge 2 commits into
iree-org:mainiree-org/iree:mainfrom
pstarkcdpr:fix-scf-while-assertpstarkcdpr/iree:fix-scf-while-assertCopy head branch name to clipboard
Open

Fix out-of-bounds crash in Stream affinity analysis for scf.while#24723
pstarkcdpr wants to merge 2 commits into
iree-org:mainiree-org/iree:mainfrom
pstarkcdpr:fix-scf-while-assertpstarkcdpr/iree:fix-scf-while-assertCopy head branch name to clipboard

Conversation

@pstarkcdpr

Copy link
Copy Markdown
Contributor

See issue #24722

The issue contains a deeper explanation of the issue and a repro case (which is the same as the lit test here).

When an scf.while carries more values through its "before" region than the op has results (i.e. some loop-carried values are not forwarded to a result via scf.condition), the affinity analysis mapped an scf.yield operand number directly onto whileOp->getResult(operandNumber). Since the "after" region yield has one operand per init operand (N) while the op may have fewer
results (M), this lead to getResult() being out of bounds.

Two independent sites made this naive mapping:

  • Affinity.cpp: in the scf.yieldscf.while branch of ValueConsumerAffinityPVS::updateFromUse, drop the whileOp->getResult(operandNumber) propagation and keep only the before-region-argument propagation. (Results are already handled by the scf.condition case.)

  • Explorer.cpp: guard the ReturnLike result-mapping fallback in walkTransitiveUses with !isa<RegionBranchTerminatorOpInterface>(ownerOp) (region-branch terminators like scf.yield are already handled correctly above) plus a use.getOperandNumber() < parent->getNumResults() bounds check.

Added regression test @scf_while_extra_loop_carried, which exercises the N > M shape (two loop-carried values, one result) that previously asserted.

Note that Claude made the fix suggestions and, while they look okay to me, I'm not at all familiar with this code.

pstarkcdpr and others added 2 commits July 17, 2026 16:09
When an scf.while carries more values through its "before" region than the
op has results (i.e. some loop-carried values are not forwarded to a result
via scf.condition), the affinity analysis mapped an scf.yield operand number
directly onto whileOp->getResult(operandNumber). Since the "after" region
yield has one operand per init operand (N) while the op may have fewer
results (M), this indexed getResult() out of bounds, tripping the
getOpResultImpl assertion (or a non-deterministic SIGSEGV in release builds).

Two independent sites made this naive mapping:

- Affinity.cpp (ValueConsumerAffinityPVS::updateFromUse): drop the
  whileOp->getResult(operandNumber) propagation in the scf.yield -> scf.while
  branch and keep only the before-region-argument propagation. While results
  are already handled by the scf.condition case.

- Explorer.cpp (walkTransitiveUses): guard the ReturnLike result-mapping
  fallback with !isa<RegionBranchTerminatorOpInterface> plus a
  getNumResults() bounds check. Region branch terminators such as scf.yield
  are already handled correctly above via the successor-operand mapping.

Adds regression test @scf_while_extra_loop_carried, which exercises the
N > M shape (two loop-carried values, one result) that previously crashed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Paul Stark <paul.stark@cdprojektred.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.

1 participant

Morty Proxy This is a proxified and sanitized view of the page, visit original site.