Skip to content

Fix SROA when loading in multiple blocks - #7694

Merged
ironcev merged 7 commits into
masterfrom
xunilrj/fix-sroa-load-multi-blocks
Jul 23, 2026
Merged

Fix SROA when loading in multiple blocks#7694
ironcev merged 7 commits into
masterfrom
xunilrj/fix-sroa-load-multi-blocks

Conversation

@xunilrj

@xunilrj xunilrj commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Description

Whilst trying to improve #7682, I came across the following bug:

SROA was generating invalid IR when an aggregated had loads across multiple blocks. When generating the scalar accesses, the older algorithm was gathering only the "last" block that had access, and incorrectly generating loads pointing to this last block, even when the load was from a previous block. A "use-before-def" problem. (see sway-ir/tests/sroa/cross_block_gep_reuse.ir).

To verify this issue this PR also creates an "SSA dominance check". We check if all "uses" are dominated by all its "defs". But this check is expensive, so, for the moment, this check is opt-in. Below we have some timings to justify that:

dominance check off:
> hyperfine "cargo r -p forc -r -- build --path fuel-o2-exports/contracts/order-book --release"
Benchmark 1: cargo r -p forc -r -- build --path fuel-o2-exports/contracts/order-book --release
  Time (mean ± σ):     11.213 s ±  0.100 s    [User: 8.347 s, System: 1.095 s]
  Range (min … max):   11.105 s … 11.383 s    10 runs

dominance check on:
> SWAY_FORCE_VERIFY_IR=true hyperfine "cargo r -p forc -r -- build --path fuel-o2-exports/contracts/order-book --release"
Benchmark 1: cargo r -p forc -r -- build --path fuel-o2-exports/contracts/order-book --release
  Time (mean ± σ):     16.663 s ±  0.577 s    [User: 13.563 s, System: 1.121 s]
  Range (min … max):   16.358 s … 18.271 s    10 runs

This PR also removes DCE and MEM2REG passes. from the SROA test. They were there to facilitate filecheck directives. As we do not use them anymore, seeing the diff as it is, is actually better.

Checklist

  • I have linked to any relevant issues.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation where relevant (API docs, the reference, and the Sway book).
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added (or requested a maintainer to add) the necessary Breaking* or New Feature labels where relevant.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

@xunilrj xunilrj self-assigned this Jul 21, 2026
@xunilrj
xunilrj temporarily deployed to fuel-sway-bot July 21, 2026 19:11 — with GitHub Actions Inactive
@codspeed-hq

codspeed-hq Bot commented Jul 21, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 25 untouched benchmarks


Comparing xunilrj/fix-sroa-load-multi-blocks (d59e465) with master (e4e44bc)

Open in CodSpeed

@xunilrj
xunilrj temporarily deployed to fuel-sway-bot July 21, 2026 20:23 — with GitHub Actions Inactive
@xunilrj

xunilrj commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@cursor bot run

@cursor

cursor Bot commented Jul 22, 2026

Copy link
Copy Markdown

I reviewed and validated the PR. Here's a summary:

Build & Tests

  • cargo build -p sway-ir compiles successfully (with Rust 1.93.0)
  • cargo clippy -p sway-ir -- -D warnings passes with no warnings
  • All 19 sway-ir tests pass (including sroa, verify, mem2reg, cse, etc.)
  • CI shows 36/42 checks successful, 1 pending (policy-bot), 5 skipped (expected for non-release)

SROA Fix (correct)
The root cause was that SROA used a single global FxHashMap<Value, Value> for replacements, then called function.replace_values() at the end. When the same GEP pointer was used across multiple blocks, later blocks overwrote earlier mappings, causing all uses to point to a get_local defined only in the last block (use-before-def). The fix correctly scopes replacements per-block via replacements_per_block and calls block.replace_values() per block. The cross_block_gep_reuse.ir test directly targets this bug.

SSA Dominance Verifier (correct)
The new SSADominanceScopeChecker properly checks that every operand is dominated by its definition, using the existing dominator infrastructure. It's gated behind context.verify_ssa_dominance and enabled in tests via run_passes_with_verify. The compute_dom_tree_from_po extraction is a clean refactor.

Minor note: When running with SWAY_FORCE_VERIFY_IR=true, the cse test fails due to a pre-existing bug where CSE incorrectly reports modified: true on idempotent runs. This is not caused by this PR — it's a latent CSE issue now exposed by routing tests through run_with_print_verify. Normal CI does not set this env var, so it doesn't affect CI.

Open in Web Open in Cursor 

@xunilrj xunilrj changed the title Fix sroa load multi blocks Fix SROA when loading in multiple blocks Jul 22, 2026
@xunilrj
xunilrj temporarily deployed to fuel-sway-bot July 22, 2026 11:14 — with GitHub Actions Inactive
@xunilrj
xunilrj temporarily deployed to fuel-sway-bot July 22, 2026 11:58 — with GitHub Actions Inactive
@xunilrj
xunilrj force-pushed the xunilrj/fix-sroa-load-multi-blocks branch from c7e3dcb to 6c4bd18 Compare July 22, 2026 12:19
@xunilrj
xunilrj temporarily deployed to fuel-sway-bot July 22, 2026 12:19 — with GitHub Actions Inactive
@xunilrj
xunilrj marked this pull request as ready for review July 22, 2026 12:26
@xunilrj
xunilrj requested a review from a team as a code owner July 22, 2026 12:26
@ironcev ironcev added compiler General compiler. Should eventually become more specific as the issue is triaged compiler: ir IRgen and sway-ir including optimization passes labels Jul 23, 2026
@ironcev

ironcev commented Jul 23, 2026

Copy link
Copy Markdown
Member

👍

@ironcev
ironcev temporarily deployed to fuel-sway-bot July 23, 2026 19:34 — with GitHub Actions Inactive
@ironcev
ironcev enabled auto-merge (squash) July 23, 2026 19:35
@ironcev
ironcev merged commit 0cd3db3 into master Jul 23, 2026
42 checks passed
@ironcev
ironcev deleted the xunilrj/fix-sroa-load-multi-blocks branch July 23, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler: ir IRgen and sway-ir including optimization passes compiler General compiler. Should eventually become more specific as the issue is triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants