Skip to content

fix(cuda-oxide): keep host-written constant memory through LTO - #1509

Open
ssoj13 wants to merge 1 commit into
NVIDIA:mainfrom
ssoj13:nvidia/fix/constant-memory-lto
Open

ssoj13 wants to merge 1 commit into
NVIDIA:mainfrom
ssoj13:nvidia/fix/constant-memory-lto

Conversation

@ssoj13

@ssoj13 ssoj13 commented Oct 13, 2026

Copy link
Copy Markdown

Host writes to #[constant] memory must remain observable after libNVVM/nvJitLink LTO. Mark these globals retained and externally_initialized, so optimization cannot fold their loads to the zero initializer or drop the symbol used by cuModuleGetGlobal.

Fixes #1507.

Port of ansidium/cuda-rust-windows#10, independently rebased onto NVIDIA main bc46b1ffb. Private device globals are unchanged. Tests cover both modern and legacy LLVM IR and distinguish host-written constant globals from private allocations.

Verified on the pinned nightly-2026-10-11, Linux/WSL2, CUDA 13.3 and RTX 3080 Ti:

  • cargo test --locked -p llvm-export -p mir-lower passes.
  • Clippy on both packages/all targets with -D warnings, formatting and SPDX checks pass.
  • A backend built from this branch runs constant_memory --materialize-cubin --arch sm_86: both 256-element launches match their respective coefficients, including rewriting the constant between launches.

The original change was authored by Alex Khal with Claude Code. This transplant and current verification were prepared with Codex; original attribution and DCO are preserved.

`#[constant]` statics are written by the host after module load
(cuModuleGetGlobal + copy), but were lowered to an ordinary zero-initialized
addrspace(4) global that was neither rooted nor marked as externally
initialized. The PTX route survived because its own internalize step keeps
every defined global public. The materialized-cubin route (libNVVM -gen-lto,
nvJitLink -lto) is whole-program LTO: it internalized the never-stored
global, folded its loads to the zero initializer and dropped the symbol, so
the host lookup failed with CUDA_ERROR_NOT_FOUND ("named symbol not found")
and the kernels computed with zeros.

create_device_global now marks constant-memory globals retained (@llvm.used,
for constants no kernel reads) and host-written; the exporter renders
host-written globals `externally_initialized`, as clang does for CUDA
__constant__ variables. Ordinary device globals are unchanged.

Signed-off-by: Alex Khal <joss13@gmail.com>
Signed-off-by: ssoj13 <96214515+ssoj13@users.noreply.github.com>
@ssoj13
ssoj13 requested a review from nihalpasham as a code owner October 13, 2026 19:29
@copy-pr-bot

copy-pr-bot Bot commented Oct 13, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@nihalpasham nihalpasham added the cuda-oxide SIMT programming model: rustc backend, cargo oxide, cuda-device, cuda-host, book label Oct 15, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda-oxide SIMT programming model: rustc backend, cargo oxide, cuda-device, cuda-host, book

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: host-written constant globals can disappear during device LTO

2 participants