Repository navigation
fix(rccl): forward inherited device options to the dispatcher compile - #12318
Merged
Merged
Conversation
✅ All Policy Checks Passed
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
lfmeadow
force-pushed
the
users/lmeadows/dl-link-inherited-flags
branch
2 times, most recently
from
September 26, 2026 19:21
93fcf59 to
c2b2c5c
Compare
Contributor
Author
|
@argus re-review |
Contributor
Author
|
@argus re-review |
lfmeadow
force-pushed
the
users/lmeadows/dl-link-inherited-flags
branch
from
September 26, 2026 20:44
6d4dcb8 to
4af6314
Compare
lfmeadow
force-pushed
the
users/lmeadows/dl-link-inherited-flags
branch
from
September 28, 2026 01:53
4af6314 to
8ee6992
Compare
The --link step compiles the dispatcher (common.cu.cpp) on its way to device.elf, so it is a device codegen step like the per-kernel objects it is linked against, but it was not given DL_INHERITED_FLAGS. Under ASAN that makes the dispatcher the single uninstrumented kernel in an otherwise instrumented image, since -fsanitize=address reaches device code only through that variable. Losing kernarg preloading there costs a memory round trip at the kernel entry the dispatcher carries. Forwarding the list as-is fails the device link with 20 relocations of the form "R_AMDGPU_REL32_LO cannot be used against symbol ...; recompile with -fPIC". The cause is -fvisibility. The HIP driver adds -fapply-global-visibility-to-externs to a device compile only when the user has not passed -fvisibility= itself, and that is what stamps hidden onto the ~3000 ncclDevFunc_* declarations the dispatcher emits. Those declarations are what keep the symbols non-preemptible, because --compile's extracted assembly re-exports each definition with a bare .globl. The drop is therefore scoped to this one consumer, as DL_LINK_INHERITED_FLAGS, rather than taken out of DL_INHERITED_FLAGS itself. That variable feeds 30 commands in this file, most of them the host fat objects (common, onerank, collectives, the dda_*, gin_* and sym_* families) that link into librccl.so; the CMake build has no version script, so dropping -fvisibility=hidden from those would export rccl internals. The filter also matches any -fvisibility= value, not just =hidden: clang suppresses -fapply-global-visibility-to-externs for all of them, and src/CMakeLists.txt sets =default under ENABLE_CODE_COVERAGE and under BUILD_TESTS with ENABLE_MPI_TESTS. Verified by two clean gfx950 builds. Release: zero relocation errors, ncclDevFunc_* in device.elf is 3064 LOCAL HIDDEN, the --link rule carries -mllvm --amdgpu-kernarg-preload-count=16 and no -fvisibility while 3382 other commands keep -fvisibility=hidden, and librccl.so exports none of the internals. ASAN: -fsanitize=address reaches the --link step, zero relocation errors, device.elf links.
lfmeadow
force-pushed
the
users/lmeadows/dl-link-inherited-flags
branch
from
September 28, 2026 03:49
8ee6992 to
a61a4c0
Compare
corey-derochie-amd
approved these changes
Sep 29, 2026
1 task done
Contributor
TheRock Submodule Bump ActivityNewest first
|
pvallem
added a commit
that referenced
this pull request
Oct 6, 2026
## Motivation `--enable-full-coverage` / `ENABLE_FULL_COVERAGE` (#10650) no longer instruments any device code on `develop`. The NCCL v2.31.2-1 sync merge (`d0f7d1966a5`, #10785) dropped the device-coverage parts of #10650 from `src/CMakeLists.txt` and `cmake/DeviceLinker.cmake`. CMake still reports `ENABLE_FULL_COVERAGE=ON`, but: - no `device-<arch>.elf` is produced next to `librccl.so` - `librccl.so` has no `__llvm_profile_hip_collect_device_data` reference - so `llvm-cov` reports 0% on every device kernel The other files #10650 touched (`DeviceCoverage.cmake`, top-level `CMakeLists.txt`, `install.sh`, `rccl-device-compile`, test runner) survived the merge and are unchanged here. ## Technical Details This cherry-picks `0beb60252bd` (#10650) and resolves it against current `develop`: - **Files that survived the merge intact:** kept develop's version (CHANGELOG, `rccl-device-compile`, test runner files). - **`src/CMakeLists.txt`:** the `ENABLE_CODE_COVERAGE` block is restored verbatim from #10650. This brings back the host/device flag split and the force-link of `__llvm_profile_hip_collect_device_data` plus the host ROCm profile runtime. - **`cmake/DeviceLinker.cmake`:** - Restores the coverage flags, device profile runtime, main-module CUID and device-ELF symlink plumbing. - The `--link` step keeps develop's `DL_LINK_INHERITED_FLAGS` (#12318) alongside `DL_COVERAGE_FLAGS` and `DL_MAIN_MODULE_CUID_FLAGS`. - The bundle `DEPENDS` keeps develop's longer object list. - The diagnostics `p2p.cu.cpp` fat object, added by the sync after #10650, now gets `DL_DEVICE_COVERAGE_FLAGS` like its sibling fat objects. Otherwise its device code would be instrumented through the inherited flags without the device profile runtime. **Second commit — host ROCm profile runtime lookup.** With the hooks restored, the instrumented `librccl.so` still failed to load on TheRock 10.1: ``` librccl.so.1: undefined symbol: _ZN14__interception17InterceptFunctionEPKcPmmm ``` - `rccl_find_host_rocm_profile_runtime` only asked the compiler for `libclang_rt.profile_rocm.a`, the per-target runtime layout. - TheRock 10.1 ships the legacy `lib/linux/libclang_rt.profile_rocm-x86_64.a`, so the lookup returned empty. - The forced `__llvm_profile_hip_collect_device_data` reference then resolved from the generic `libclang_rt.profile-x86_64.a`. Its ROCm collector object references `__interception::InterceptFunction` without defining it. The lookup now tries the arch-suffixed name after the per-target one. A new test, `test_host_probe_finds_legacy_arch_suffixed_runtime`, covers this and fails without the fix. No behaviour change without `ENABLE_FULL_COVERAGE`: every restored line is gated on it. ## Issue Tracking JIRA ID: AICOMRCCL-2318 ## Test Plan Ruby (MI350X, gfx950), TheRock ROCm 10.1. Same command on this branch and on `develop`: ```bash ./install.sh --debug -t --enable-full-coverage --ninja --amdgpu_targets=gfx950 ``` Then inspect the build and run `rccl-UnitTests --gtest_filter='AllReduce.*:AllGather.*:Broadcast.*'` with `LLVM_PROFILE_FILE` set, merge, and `llvm-cov report librccl.so -object device-gfx950.elf`. ## Test Result | `--enable-full-coverage`, TheRock 10.1, gfx950 | `develop` | this PR | | --- | --- | --- | | Build | pass | pass | | `ENABLE_FULL_COVERAGE` in CMakeCache | ON | ON | | `device-gfx950.elf` produced | **no** | yes | | device ELF sections | — | `__llvm_prf_cnts __llvm_prf_data __llvm_covmap __llvm_covfun` | | `__llvm_profile_hip_collect_device_data` in `librccl.so` | 0 | 1 | - `tools/scripts/test_runner` unit suite: 112/112 pass (`python3 -m unittest discover -s tests -t .`; needs an exec-capable `TMPDIR`, because the fake-compiler tests fail on a `noexec` `/tmp`). - Runtime device coverage from the gtest subset: results to follow in a comment. ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/rocm-systems/blob/develop/CONTRIBUTING.md. --------- Signed-off-by: Praneeth Vallem <Praneeth.Vallem@amd.com> Co-authored-by: Atul Kulkarni <atul.kulkarni@amd.com>
alex-breslow-amd
pushed a commit
that referenced
this pull request
Oct 28, 2026
…eline (#12394) JIRA ID : LCOMPILER-2794 Replaces #12313, which was closed by accident. Same changes, rebased onto current develop. Feature suffixes were being lost in the device linker pipeline. This caused features like `xnack+` to be lost when compiling for ASAN. ## What changed These changes keep both the bare processor name and the feature string. One site outside the device linker pipeline also dropped the feature string: the rocSHMEM build. This is also fixed. ## Tests New cases in the canonical driver suite at `tools/scripts/test_runner/tests/`. ## Notes for review One of the PRs replacing the closed #9763 and #12221. Nothing here depends on the others, though #12318 touches the same file and whichever lands second will need a rebase. ASAN device code needs both this and #12314: the latter decides *which* targets an ASAN build asks for, and this PR makes the request reach codegen. They can land in either order, but kernels are only instrumented once both are in. Verified with clean builds at `gfx950` and `gfx942:xnack+`, plus a 3-arch ASAN build, on ROCm clang 23 and clang 24. After the rebase, re-verified with clean `gfx950` ASAN builds, one with tests and one with `--rocshmem`: no `ignoring '-fsanitize=address'` warnings. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
JIRA ID : LCOMPILER-2794
The
--linkstep compiles the dispatcher (common.cu.cpp) on its way todevice.elf, so it is a device codegen step like the per-kernel objects it islinked against, but it was not given
${DL_INHERITED_FLAGS}. Under ASAN thatleaves the dispatcher as the one uninstrumented kernel in an otherwise
instrumented image, since
-fsanitize=addressreaches device code only throughthat variable. The dispatcher also carries the kernel entry, so losing kernarg
preloading there costs a memory round trip at every launch.
Why the forward needs a second list
Forwarding
${DL_INHERITED_FLAGS}as-is fails the device link with 20relocations of the form
R_AMDGPU_REL32_LO cannot be used against symbol ...; recompile with -fPIC. The cause is-fvisibility. The HIP driver adds-fapply-global-visibility-to-externsto a device compile only when the userhas not passed
-fvisibility=itself, and that is what stamps hidden onto the~3000
ncclDevFunc_*declarations the dispatcher emits. Those declarations arewhat keep the symbols non-preemptible, because
--compile's extracted assemblyre-exports each definition with a bare
.globl.So the
--linkstep gets its ownDL_LINK_INHERITED_FLAGS, which isDL_INHERITED_FLAGSminus any-fvisibility=option. Two details matter:DL_INHERITED_FLAGSfeeds 30commands in this file, most of them the host fat objects —
common,onerank,collectives, thedda_*,gin_*andsym_*families — thatlink into
librccl.so. The CMake build has no version script, so taking-fvisibility=hiddenout of the shared list would export rccl internals.-fvisibility=value, not just=hidden. Clangsuppresses
-fapply-global-visibility-to-externsfor all of them, andsrc/CMakeLists.txtsets=defaultunderENABLE_CODE_COVERAGE, and underBUILD_TESTSwith eitherENABLE_MPI_TESTSor a Debug build onROCm >= 6.4, all of which reach here.
The result is purely additive against develop:
DL_INHERITED_FLAGSand thecomment block above it are unchanged, and the diff is the new loop plus the
forward.
Tests
Two clean
gfx950builds.Release: zero relocation errors;
ncclDevFunc_*indevice.elfis 3064LOCAL HIDDEN, unchanged from develop; the--linkrule inbuild.ninjacarries
-mllvm --amdgpu-kernarg-preload-count=16and no-fvisibility, while3382 other commands still carry
-fvisibility=hidden;librccl.sohas 1212dynamic symbols and exports none of
ncclAllReduce_impl,ncclTopoGetSystemor
bootstrapNetInit.ASAN (
./install.sh --ninja --address-sanitizer --amdgpu_targets gfx950):-fsanitize=addressreaches the--linkstep, the build completes 3996/3996with zero relocation errors, and
device.elflinks.The ASAN device image is still uninstrumented — flags
0x54f(xnack= ANY),zero asan symbols — because
DeviceLinker.cmakereduces the target to baregfx950before codegen. That is #12394's job, and this PR neither causes norfixes it.
Notes for review
One of the PRs replacing the closed #9763 and #12221. No ordering requirement
against the others, though #12394 touches the same file and whichever lands
second will need a rebase.
Update after review
The first version filtered
-fvisibility=hiddenout ofDL_INHERITED_FLAGSitself. Review caught that this was wrong in both directions: too broad,
because the shared list feeds the host objects described above, and too narrow,
because the alternation matched only the literal
=hiddenwhile=defaultislive in two configs. Both are fixed by the scoped, value-agnostic list. The
claim that
--linkwas the only codegen step without the flags was alsofalse —
device_irand the rocSHMEM constmem bitcode compile still lack them —and has been dropped.