Skip to content

Run ExpandAtomicModify when lowering for the JIT#3178

Draft
vchuravy wants to merge 3 commits into
mainfrom
vc/atomicmodify
Draft

Run ExpandAtomicModify when lowering for the JIT#3178
vchuravy wants to merge 3 commits into
mainfrom
vc/atomicmodify

Conversation

@vchuravy

Copy link
Copy Markdown
Member

Julia 1.13 (JuliaLang/julia#57010) emits @atomic modify operations as
calls to the julia.atomicmodify.* pseudo-intrinsic family, which must
be expanded to atomicrmw/cmpxchg by the ExpandAtomicModify pass before
machine code emission; there is no runtime fallback symbol. Since our
legalization pipeline never ran this pass, the unexpanded calls reached
the ORC JIT as unresolvable symbols and aborted the process.

Mirror Julia's pipeline placement (after FinalLowerGC, before
LowerPTLS) in addJuliaLegalizationPasses!. LLVM.jl does not wrap this
pass yet, so define the pass-name wrapper locally.

Differentiating through julia.atomicmodify in reverse mode still
requires support for the pseudo-intrinsic in Enzyme proper, which is
handled separately.

Fixes #3086

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

main 55809ef... main / 55809ef...
basics/make_zero/namedtuple 0.0535 ± 0.002 μs 0.0553 ± 0.0029 μs 0.969 ± 0.062
basics/make_zero/struct 0.281 ± 0.009 μs 0.279 ± 0.007 μs 1.01 ± 0.041
basics/overhead 4.34 ± 0.01 ns 4.34 ± 0.01 ns 1 ± 0.0033
basics/remake_zero!/namedtuple 0.223 ± 0.0095 μs 0.225 ± 0.012 μs 0.992 ± 0.068
basics/remake_zero!/struct 0.227 ± 0.011 μs 0.234 ± 0.015 μs 0.969 ± 0.076
fold_broadcast/multidim_sum_bcast/1D 10.2 ± 0.25 μs 10.2 ± 0.28 μs 1 ± 0.037
fold_broadcast/multidim_sum_bcast/2D 12 ± 0.3 μs 12.1 ± 0.33 μs 0.997 ± 0.037
time_to_load 1.48 ± 0.018 s 1.59 ± 0.0097 s 0.931 ± 0.013

Benchmark Plots

A plot of the benchmark results has been uploaded as an artifact at https://github.com/EnzymeAD/Enzyme.jl/actions/runs/28082299634/artifacts/7842962472.

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.18%. Comparing base (000acf6) to head (e40014a).
⚠️ Report is 45 commits behind head on main.

❗ There is a different number of reports uploaded between BASE (000acf6) and HEAD (e40014a). Click for more details.

HEAD has 28 uploads less than BASE
Flag BASE (000acf6) HEAD (e40014a)
34 6
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #3178       +/-   ##
===========================================
- Coverage   70.61%   51.18%   -19.44%     
===========================================
  Files          66       13       -53     
  Lines       21334     1264    -20070     
===========================================
- Hits        15066      647    -14419     
+ Misses       6268      617     -5651     

☔ 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.
vchuravy and others added 3 commits June 24, 2026 09:08
Julia 1.13 (JuliaLang/julia#57010) emits `@atomic` modify operations as
calls to the `julia.atomicmodify.*` pseudo-intrinsic family, which must
be expanded to atomicrmw/cmpxchg by the ExpandAtomicModify pass before
machine code emission; there is no runtime fallback symbol. Since our
legalization pipeline never ran this pass, the unexpanded calls reached
the ORC JIT as unresolvable symbols and aborted the process.

Mirror Julia's pipeline placement (after FinalLowerGC, before
LowerPTLS) in addJuliaLegalizationPasses!. LLVM.jl does not wrap this
pass yet, so define the pass-name wrapper locally.

Differentiating *through* julia.atomicmodify in reverse mode still
requires support for the pseudo-intrinsic in Enzyme proper, which is
handled separately.

Fixes #3086

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the active float atomic-modify test: Julia only emits
julia.atomicmodify for integer-typed pointer-free fields; float fields
still lower to an inline cmpxchg loop, whose reverse-mode
differentiation is a pre-existing, unrelated limitation.

Instead test an atomic counter inside a Duplicated struct, which
exercises Enzyme replicating the modification on the shadow object.
Requires julia.atomicmodify support in Enzyme proper.

Co-Authored-By: Claude Fable 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

1 participant