Skip to content
This repository was archived by the owner on Jan 18, 2026. It is now read-only.

flake: update llvmlite and llvm#2859

Merged
sbourdeauducq merged 5 commits intom-labs:masterfrom
fsagbuya:update_llvmlite
Oct 8, 2025
Merged

flake: update llvmlite and llvm#2859
sbourdeauducq merged 5 commits intom-labs:masterfrom
fsagbuya:update_llvmlite

Conversation

@fsagbuya
Copy link
Contributor

@fsagbuya fsagbuya commented Sep 19, 2025

Nix has already dropped support for llvm_15 which will be reflected in the next flake update:

 error: lld_15 has been removed, as it is unmaintained and obsolete

Also, there is now a recent release of llvmlite which supports llvm_20.

Tests:

nix build .#artiq -L

python3.13-artiq> PASS: ARTIQ :: time/advance.py (217 of 222)
python3.13-artiq> PASS: ARTIQ :: time/parallel.py (218 of 222)
python3.13-artiq> PASS: ARTIQ :: time/advance_mu.py (219 of 222)
python3.13-artiq> PASS: ARTIQ :: try_loop/try_finally_while_try_reraise.py (220 of 222)
python3.13-artiq> PASS: ARTIQ :: try_loop/try_finally_while_try_finally_break.py (221 of 222)
python3.13-artiq> PASS: ARTIQ :: try_loop/try_finally_while_try_return.py (222 of 222)
python3.13-artiq> Testing Time: 37.25s
python3.13-artiq> Total Discovered Tests: 222
python3.13-artiq>   Passed           : 220 (99.10%)
python3.13-artiq>   Expectedly Failed:   2 (0.90%)

nix build .#hydraJobs.kc705-hitl -L

kc705-hitl> ----------------------------------------------------------------------
kc705-hitl> Ran 225 tests in 124.440s
kc705-hitl> 
kc705-hitl> OK (skipped=145, expected failures=1)
kc705-hitl> buildPhase completed in 4 minutes 15 seconds

@fsagbuya fsagbuya marked this pull request as draft September 19, 2025 08:16
@dnadlinger
Copy link
Collaborator

dnadlinger commented Sep 29, 2025

This runs some experiments, but causes an issue in code using integer modulo (e.g. just print(10 % 4)):

root:Terminating with exception (LoadError: cannot load kernel: symbol lookup error: __py_modsi3)
Traceback (most recent call last):
  File "/home/ion/scratch/artiq/artiq/master/worker_impl.py", line 484, in main
    exp_inst.run()
    ~~~~~~~~~~~~^^
  File "/home/ion/scratch/caqtus/caqtus/startup.py", line 99, in run
    self.krun()
    ~~~~~~~~~^^
  File "/home/ion/scratch/artiq/artiq/language/core.py", line 54, in run_on_core
    return getattr(self, arg).run(run_on_core, ((self,) + k_args), k_kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ion/scratch/artiq/artiq/coredevice/core.py", line 180, in run
    self._run_compiled(kernel_library, embedding_map, symbolizer, demangler)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ion/scratch/artiq/artiq/coredevice/core.py", line 167, in _run_compiled
    self.comm.load(kernel_library)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/home/ion/scratch/artiq/artiq/coredevice/comm_kernel.py", line 390, in load
    raise LoadError(self._read_string())
artiq.coredevice.comm_kernel.LoadError: cannot load kernel: symbol lookup error: __py_modsi3

The way the new passs manger pipeline is set up, __py_modsi3 does not get inlined, and remains in the final ELF as a defined weak symbol (linkonce_odr on the LLVM side). I suspect – but have not checked – that our runtime loader doesn't handle weak symbols, as they usually don't crop up.

Either way, the underlying issue causing this to surface now appears to be that the draft PR disables inlining completely (except for alwaysinline, which I don't think we use). Just reverting to the default pass builder -Os pipeline fixes the issue:

--- a/artiq/compiler/targets.py
+++ b/artiq/compiler/targets.py
@@ -107,34 +107,18 @@ class Target:
         return llmachine

     def optimize(self, llmodule):
-        llpassmgr = llvm.ModulePassManager()
-
-        # Start by cleaning up after our codegen and exposing as much
-        # information to LLVM as possible.
-        llpassmgr.add_constant_merge_pass()
-        llpassmgr.add_simplify_cfg_pass()
-        llpassmgr.add_instruction_combine_pass()
-        llpassmgr.add_sroa_pass()
-        llpassmgr.add_dead_code_elimination_pass()
-        llpassmgr.add_post_order_function_attributes_pass()
-        llpassmgr.add_global_opt_pass()
-
-        # Now, actually optimize the code.
-        llpassmgr.add_always_inliner_pass()
-        llpassmgr.add_ipsccp_pass()
-        llpassmgr.add_instruction_combine_pass()
-        llpassmgr.add_new_gvn_pass()
-        llpassmgr.add_simplify_cfg_pass()
-
-        # Clean up after optimizing.
-        llpassmgr.add_dead_arg_elimination_pass()
-        llpassmgr.add_global_dead_code_eliminate_pass()
-
-        # Create PassBuilder with required arguments for new pass manager
         llmachine = self.target_machine()
-        pto = llvm.create_pipeline_tuning_options()
-        pb = llvm.create_pass_builder(llmachine, pto)

+        pto = llvm.create_pipeline_tuning_options(size_level=1)
+
+        # This combination of levels gets mapped to the -Os PassManagerBuilder default in
+        # llvmlite 0.45. The mapping is slightly nonsensical in that -Oz (which is more
+        # aggressively optimizing for size at the expense of runtime) is accessed via
+        # speed_level=size_level=2.
+        pto.speed_level = 1
+
+        pb = llvm.create_pass_builder(llmachine, pto)
+        llpassmgr = pb.getModulePassManager()
         llpassmgr.run(llmodule, pb)

     def compile(self, module):

If we want to optimise our pass pipeline, we should probably take the current -O2 or -Os (as per the above code) as a starting point and prune down passes that don't help us from there, rather than the other way round.

@dnadlinger
Copy link
Collaborator

(see numba/llvmlite#1306 for the size_level issue pointed out in the comment)

@fsagbuya fsagbuya marked this pull request as ready for review October 3, 2025 05:23
@sbourdeauducq
Copy link
Member

sbourdeauducq commented Oct 6, 2025

Kernels fail to run on the device with this error:

panic at runtime/kernel.rs:28:9: failed to load kernel CPU image (ksupport.elf): unexpected load address/offset
backtrace for software version 9.0+unknown.beta;nist_clock:
0x40030758
0x4000b120
0x4001a94c
0x40025bc4
0x4000c9a4
0x4000c994
0x4002c568
0x40006d50
0x400190d4
0x4001907c
0x4002fa5c
halting.
use `artiq_coremgmt config write -s panic_reset 1` to restart instead

@fsagbuya please use readelf and other llvm/binutils tools to debug this.

@fsagbuya fsagbuya marked this pull request as draft October 6, 2025 04:33
@dnadlinger
Copy link
Collaborator

Interesting; some people here are supposedly using recent ARTIQ with this patch (on Kasli v2, but that seems unlikely to be related).

@fsagbuya fsagbuya marked this pull request as ready for review October 7, 2025 10:00
@fsagbuya
Copy link
Contributor Author

fsagbuya commented Oct 7, 2025

Kernels fail to run on the device with this error:

panic at runtime/kernel.rs:28:9: failed to load kernel CPU image (ksupport.elf): unexpected load address/offset

@fsagbuya please use readelf and other llvm/binutils tools to debug this.

@sbourdeauducq builds now with this commit: 0717fb7

@fsagbuya fsagbuya changed the title flake: update llvmlite flake: update llvmlite and llvm Oct 7, 2025
LLVM lld 17+ adds PT_RISCV_ATTRIBUTES program header, increasing
ELF header size from 0x74 to 0x94 bytes and breaking runtime
validation. Discard the section to restore expected header size.

The section contains only metadata and PT_RISCV_ATTRIBUTES is
now deprecated in RISC-V ELF psABI.
@sbourdeauducq sbourdeauducq merged commit ee6bb2f into m-labs:master Oct 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants