Skip to content

fix(rocsparse): restrict coverage instrumentation to host code - #12317

Open
kliegeois wants to merge 5 commits into
ROCm:developfrom
kliegeois:task/rocsparse-codecov-system-rocprim
Open

kliegeois wants to merge 5 commits into
ROCm:developfrom
kliegeois:task/rocsparse-codecov-system-rocprim

Conversation

@kliegeois

@kliegeois kliegeois commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Problem

Every rocSPARSE codecov job has failed since Sep 16. All tests pass, then the binary dies while dumping the profile:

[  PASSED  ] 68413 tests.
:0:/TheRock/rocm-systems/projects/clr/hipamd/src/hip_global.cpp:209 : Cannot create GlobalVar Obj for symbol: __profd__ZN7rocprim..._radix_sort_block_sort...
Subprocess aborted

This is not specific to any PR. develop codecov was last green on build #288 (Sep 15) with libamdhip64.so.7.13.99004-3309; #289 onward all fail and run libamdhip64.so.7.16.26370. hipBLASLt hits the identical abort (#12268), there on a kernel in its own client test code.

Cause

ROCm 7.16 enables source-based coverage for HIP device code. Two things then land in the device image, and the runtime aborts in hip_global.cpp:209 when it tries to register either one:

  1. -fprofile-instr-generate -fcoverage-mapping on a HIP compile instruments device code and emits a __profd_* global per instantiated kernel.
  2. -fprofile-instr-generate on a HIP link pulls the AMDGPU profile runtime into the device image, which contributes a __llvm_profile_sections_<hash> section-bounds table per TU.

Upstream, a failed lookup of these is a PROF_WARN in InstrProfilingPlatformROCm.cpp; this CLR turns it into a fatal guarantee. Any such symbol triggers it regardless of which header it came from, so scoping includes as SYSTEM or de-instrumenting individual translation units does not help — it only changes which symbol dies first.

Fix

Keep coverage on the host side only, on rocsparse and the unit-test targets:

  • compile with -Xarch_device -fno-profile-instr-generate -fno-coverage-mapping, so no __profd_* globals are emitted;
  • link with -Xarch_host -fprofile-instr-generate, so the device image gets no profile runtime while the host still links libclang_rt.profile.

Verified against the driver that the amdgcn-amd-amdhsa job receives neither flag while the x86_64 host job keeps -fprofile-instrument=clang and -fcoverage-mapping, and that a host .profraw is still written after the link change. The SHELL: prefixes keep CMake from de-duplicating the repeated -Xarch_* and silently re-enabling device instrumentation.

Host-side coverage is unchanged. Device kernel bodies drop out of the coverage mapping, which is the cost of unblocking the job until the runtime side is fixed.

Notes

  • Tracked in AISPARSE-778.
  • The HIP runtime should not abort here; that affects every library in the monorepo and needs a fix on the CLR side. This change only unblocks rocSPARSE.

@therock-pr-bot

therock-pr-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass
Forbidden Files ✅ Pass
🧪 Unit Test ✅ Pass PR does not contain code files — Unit Test auto-passed
🔎 pre-commit ✅ Pass
🚫 Draft PR 🔜 To Be Enabled
🚩 Feature Flag 🔜 To Be Enabled
📊 Code Coverage 🔜 To Be Enabled
🤖 therock-pr-bot ✅ Pass

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

Code coverage builds pass -fprofile-instr-generate -fcoverage-mapping to
HIP compilations, so clang instruments device code as well and emits a
__profd_* device global for every instantiated kernel. When the profile is
dumped at process exit the HIP runtime tries to register those globals and
fails, so rocsparse-test dies after every test has already passed and the
coverage target never produces a report.

Pass -fno-profile-instr-generate -fno-coverage-mapping to the device
compilation only, via -Xarch_device, on the library and unit-test targets.
Host-side coverage is unchanged; no device globals are emitted, so the
profile dump completes.

AISPARSE-778

Co-authored-by: Cursor <cursoragent@cursor.com>
@kliegeois
kliegeois force-pushed the task/rocsparse-codecov-system-rocprim branch from 6306fd5 to 64f046b Compare September 18, 2026 22:45
@kliegeois kliegeois changed the title fix(rocsparse): exclude rocPRIM from coverage instrumentation fix(rocsparse): restrict coverage instrumentation to host code Sep 18, 2026
kliegeois and others added 4 commits September 18, 2026 18:45
Restricting the coverage instrumentation to host compilation removed the
__profd_* device globals, but the HIP runtime still aborted at profile
dump, now on __llvm_profile_sections_<hash>. That symbol is the per-TU
section bounds table contributed by the AMDGPU profile runtime, which the
driver links into the device image whenever -fprofile-instr-generate is
passed to a HIP link.

Scope the link-time flag to the host with -Xarch_host, so the device image
carries no profile runtime and the host still links libclang_rt.profile.

AISPARSE-778

Co-authored-by: Cursor <cursoragent@cursor.com>
-Xarch_host did not keep device profiling out of the image: the driver
decides from the original arguments, so a HIP link that mentions
-fprofile-instr-generate still forwards it to clang-linker-wrapper as
--device-compiler=amdgcn-amd-amdhsa=-fprofile-instr-generate. The device
image then carries the AMDGPU profile runtime and its per-TU
__llvm_profile_sections_<hash> table, which the HIP runtime aborts on
while registering it at profile dump.

Link libclang_rt.profile-x86_64.a directly, with -u__llvm_profile_runtime
to pull in the at-exit writer, and stop passing -fprofile-instr-generate
to the link at all. Confirmed locally that an instrumented shared library
built this way still writes a .profraw when loaded by an uninstrumented
executable.

AISPARSE-778

Co-authored-by: Cursor <cursoragent@cursor.com>
Reapplies the direct link of the host profile runtime, this time naming
the archives it depends on. libclang_rt.profile is not self-contained: its
ROCm platform object references __prof_rocm device-drain helpers and the
symbol-interception layer, so linking it alone left librocsparse.so with
undefined references and broke the gfortran-linked samples.

Resolve clang_rt.profile, clang_rt.profile_rocm, clang_rt.interception and
clang_rt.sanitizer_common at configure time with --print-file-name, taking
whichever exist, and link them as a group since they reference each other.
This keeps -fprofile-instr-generate off the HIP link, which is what makes
the driver add --device-linker=...profile.bc and put the device profile
runtime into the device image.

AISPARSE-778

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov

codecov Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #12317      +/-   ##
===========================================
+ Coverage    70.78%   70.80%   +0.02%     
===========================================
  Files         2842     2842              
  Lines       465020   465021       +1     
  Branches     68499    68503       +4     
===========================================
+ Hits        329152   329223      +71     
+ Misses      112174   112093      -81     
- Partials     23694    23705      +11     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 46.40% <ø> (ø) Carriedforward from 26b228b
TensileLite-Unit 76.10% <ø> (ø) Carriedforward from 26b228b
hipBLAS 90.62% <ø> (ø) Carriedforward from 26b228b
hipBLASLt 35.24% <ø> (ø) Carriedforward from 26b228b
hipCUB 82.68% <ø> (ø) Carriedforward from 26b228b
hipDNN 87.01% <ø> (ø) Carriedforward from 26b228b
hipFFT 43.25% <ø> (ø) Carriedforward from 26b228b
hipRAND 76.12% <ø> (ø) Carriedforward from 26b228b
hipSOLVER 68.96% <ø> (ø) Carriedforward from 26b228b
hipSPARSE 86.99% <ø> (ø) Carriedforward from 26b228b
rocBLAS 48.31% <ø> (ø) Carriedforward from 26b228b
rocFFT 51.59% <ø> (ø) Carriedforward from 26b228b
rocRAND 57.42% <ø> (ø) Carriedforward from 26b228b
rocSOLVER 76.83% <ø> (ø) Carriedforward from 26b228b
rocSPARSE 74.70% <ø> (+0.09%) ⬆️
rocThrust 93.15% <ø> (ø) Carriedforward from 26b228b

*This pull request uses carry forward flags. Click here to find out more.
see 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants