|
| 1 | +#!/bin/bash |
| 2 | +# HipDevCov check driver. |
| 3 | +# |
| 4 | +# Args (passed from the Makefile): |
| 5 | +# $1 = AOMP (LLVM dir containing bin/clang, llvm-profdata, llvm-objdump) |
| 6 | +# $2 = GPU arch (e.g. gfx90a, may include :features) |
| 7 | +# $3 = FILECHECK (path to FileCheck) |
| 8 | +# $4 = ROCM_PATH (HIP/ROCm install for --rocm-path and libamdhip64) |
| 9 | +# |
| 10 | +# Returns 0 only if BOTH the host-shadow kernel and the module-only kernel are |
| 11 | +# present in the merged profile (the latter requires the HSA drain). |
| 12 | + |
| 13 | +set -u |
| 14 | +AOMP="$1"; ARCH="$2"; FILECHECK="$3"; ROCM="$4" |
| 15 | +CLANG="$AOMP/bin/clang" |
| 16 | +PROFDATA="$AOMP/bin/llvm-profdata" |
| 17 | +OBJDUMP="$AOMP/bin/llvm-objdump" |
| 18 | +COV="$AOMP/bin/llvm-cov" |
| 19 | + |
| 20 | +here="$(cd "$(dirname "$0")" && pwd)" |
| 21 | +cd "$here" || exit 1 |
| 22 | + |
| 23 | +# Capability gate: skip cleanly on toolchains that do not ship the device |
| 24 | +# profile runtime / HSA drain yet (so this does not red-fail CI before the |
| 25 | +# feature lands). A real, drain-capable toolchain has the amdgcn device profile |
| 26 | +# RT and the host drain symbol. |
| 27 | +resdir="$("$CLANG" -print-resource-dir 2>/dev/null)" |
| 28 | +devrt="$resdir/lib/amdgcn-amd-amdhsa/libclang_rt.profile.a" |
| 29 | +if [ ! -f "$devrt" ]; then |
| 30 | + echo "SKIP HipDevCov: no device profile runtime at $devrt" |
| 31 | + exit 0 |
| 32 | +fi |
| 33 | +if ! ls "$resdir"/lib/*/libclang_rt.profile_rocm*.a >/dev/null 2>&1; then |
| 34 | + echo "SKIP HipDevCov: no host profile_rocm runtime (HSA drain) in toolchain" |
| 35 | + exit 0 |
| 36 | +fi |
| 37 | + |
| 38 | +set -e |
| 39 | +rm -f ./*.profraw mod.co merged.profdata builder builder.*.host-* \ |
| 40 | + builder.*.hip-amdgcn-amd-amdhsa--* 2>/dev/null || true |
| 41 | + |
| 42 | +# 1. Build mod.hip as a full executable so the device link gets the device |
| 43 | +# profile RT, then extract its device code object as the loadable mod.co. |
| 44 | +"$CLANG" -x hip --offload-arch="$ARCH" -fno-gpu-rdc -DBUILD_MODULE_EXE \ |
| 45 | + -fprofile-instr-generate -fcoverage-mapping --rocm-path="$ROCM" \ |
| 46 | + mod.hip -o builder -L"$ROCM/lib" -lamdhip64 -Wl,-rpath,"$ROCM/lib" |
| 47 | +"$OBJDUMP" --offloading builder >/dev/null 2>&1 || true |
| 48 | +co="$(ls builder*.hip-amdgcn-amd-amdhsa--*gfx* 2>/dev/null | head -1)" |
| 49 | +if [ -z "$co" ]; then |
| 50 | + echo "FAIL HipDevCov: could not extract device code object from builder" |
| 51 | + exit 1 |
| 52 | +fi |
| 53 | +cp "$co" mod.co |
| 54 | + |
| 55 | +# 2. main is built by the smoke harness (TESTNAME=main). Build it here too if it |
| 56 | +# is missing, so the script also works when run standalone. |
| 57 | +if [ ! -x ./main ]; then |
| 58 | + "$CLANG" -x hip --offload-arch="$ARCH" -fno-gpu-rdc \ |
| 59 | + -fprofile-instr-generate -fcoverage-mapping --rocm-path="$ROCM" \ |
| 60 | + main.hip -o main -L"$ROCM/lib" -lamdhip64 -Wl,-rpath,"$ROCM/lib" |
| 61 | +fi |
| 62 | + |
| 63 | +# 3. Run. Device .profraw files are written to CWD (arch-prefixed for the |
| 64 | +# host-shadow drain, arch.hsa<N>-prefixed for the HSA drain); the host one |
| 65 | +# goes to LLVM_PROFILE_FILE. |
| 66 | +rm -f ./*.profraw |
| 67 | +LLVM_PROFILE_FILE="$here/host.profraw" \ |
| 68 | + LD_LIBRARY_PATH="$ROCM/lib:${LD_LIBRARY_PATH:-}" \ |
| 69 | + ./main |
| 70 | + |
| 71 | +# 4. Merge host + all device profraws and assert both kernels are present. |
| 72 | +"$PROFDATA" merge -sparse -o merged.profdata ./*.profraw |
| 73 | +"$PROFDATA" show --all-functions merged.profdata | "$FILECHECK" check.txt |
| 74 | + |
| 75 | +# 5. Sanity (non-fatal): llvm-cov can consume the merged device+host profile. |
| 76 | +# main's covmap only describes host_kernel/main, so llvm-cov warns about the |
| 77 | +# module-only function; that is expected, hence non-fatal. |
| 78 | +"$COV" report ./main -instr-profile=merged.profdata >/dev/null 2>&1 || true |
| 79 | + |
| 80 | +echo "HipDevCov PASSED" |
0 commit comments