Skip to content

Demote unordered atomic accesses for SPIR-V targets - #924

Merged
maleadt merged 1 commit into
mainfrom
tb/demote-unordered-atomics
Sep 7, 2026
Merged

Demote unordered atomic accesses for SPIR-V targets#924
maleadt merged 1 commit into
mainfrom
tb/demote-unordered-atomics

Conversation

@maleadt

@maleadt maleadt commented Sep 6, 2026

Copy link
Copy Markdown
Member

Julia marks loads and stores of heap references unordered, so that a read racing with the GC or with another thread's write cannot observe a torn pointer. There is no device GC for these orderings to protect against, but not every back-end can express them: SPIR-V's OpAtomicLoad/OpAtomicStore only take scalar integer or floating-point operands, so the Khronos translator turns an unordered load of a pointer into an invalid pointer-typed atomic ("AtomicLoad: expected Result Type to be integer or float scalar type" from spirv-val; Intel's compiler fails on an undefined __spirv_AtomicLoad(long**, int, int)). The LLVM SPIR-V back-end already lowers such loads to plain OpLoads. With oneAPI.jl gaining a device allocator, kernels that read boxed fields now reach this on Julia 1.12+.

Move the Metal target's demote_unordered_atomics! next to the other shared post-optimization rewrites and run it from the SPIR-V target's finish_ir! too. The end-to-end test compiles an unordered pointer load and store through both SPIR-V code paths with validation enabled.

Julia marks loads and stores of heap references `unordered`, so that a read
racing with the GC or with another thread's write cannot observe a torn
pointer. There is no device GC for these orderings to protect against, but
not every back-end can express them: SPIR-V's OpAtomicLoad/OpAtomicStore
only take scalar integer or floating-point operands, so the Khronos
translator turns an `unordered` load of a pointer into an invalid
pointer-typed atomic ("AtomicLoad: expected Result Type to be integer or
float scalar type" from spirv-val; Intel's compiler fails on an undefined
`__spirv_AtomicLoad(long**, int, int)`). The LLVM SPIR-V back-end already
lowers such loads to plain OpLoads. With oneAPI.jl gaining a device
allocator, kernels that read boxed fields now reach this on Julia 1.12+.

Move the Metal target's `demote_unordered_atomics!` next to the other
shared post-optimization rewrites and run it from the SPIR-V target's
`finish_ir!` too. The end-to-end test compiles an `unordered` pointer load
and store through both SPIR-V code paths with validation enabled.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.42%. Comparing base (370be42) to head (73e0c48).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #924   +/-   ##
=======================================
  Coverage   85.42%   85.42%           
=======================================
  Files          29       29           
  Lines        5583     5584    +1     
=======================================
+ Hits         4769     4770    +1     
  Misses        814      814           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maleadt

maleadt commented Sep 6, 2026

Copy link
Copy Markdown
Member Author

CI failure unrelated, looks like Julia+Asserts has regressed and fails to precompile e.g. Parsers.jl
EDIT: JuliaLang/julia#63036

maleadt added a commit to JuliaLang/julia that referenced this pull request Sep 6, 2026
Sinking an inner loop's `gc_preserve_end` to an exit that also leaves the
loop containing its `gc_preserve_begin` makes the token live out of that
outer loop. LCSSA cannot insert token PHIs, so subsequent loop cloning can
leave uses that are no longer dominated by their definition. This causes a
verifier failure while precompiling Parsers 3.0.0 on Julia 1.12 with LLVM
assertions in JuliaGPU/GPUCompiler.jl#924.

Only sink ends to exits within the begin's loop, or to any exit if the
begin is outside all loops. Omitting an end conservatively extends the
preserve region, which GC lowering already supports.

CI failure: https://github.com/JuliaGPU/GPUCompiler.jl/actions/runs/34050391805/job/101532856212

Assisted-by: Claude Code (Fable 5.1)
Assisted-by: Codex (GPT-6)
@maleadt
maleadt merged commit d6c36ac into main Sep 7, 2026
32 of 33 checks passed
@maleadt
maleadt deleted the tb/demote-unordered-atomics branch September 7, 2026 05:44
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