[compiler-rt] [PGO][HIP] Support hipModuleLoad in offload PGO (PR #211875)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 24 11:47:00 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Yaxun (Sam) Liu (yxsamliu)
<details>
<summary>Changes</summary>
Offload PGO finds profile sections by inspecting the image passed to
hipModuleLoadData. hipModuleLoad only provides a file name, so its device
profile counters were not collected.
After a successful hipModuleLoad, read the code object with the existing
profile file-buffer helper and register it through the same path used by
in-memory module loads.
---
Full diff: https://github.com/llvm/llvm-project/pull/211875.diff
2 Files Affected:
- (modified) compiler-rt/lib/profile/InstrProfilingPlatformROCm.cpp (+37-3)
- (added) compiler-rt/test/profile/AMDGPU/device-module-load-file.hip (+63)
``````````diff
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformROCm.cpp b/compiler-rt/lib/profile/InstrProfilingPlatformROCm.cpp
index 93d3cbce38de8..cae2e118e9f1a 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformROCm.cpp
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformROCm.cpp
@@ -9,6 +9,7 @@
extern "C" {
#include "InstrProfiling.h"
#include "InstrProfilingPort.h"
+#include "InstrProfilingUtil.h"
}
#include "interception/interception.h"
@@ -1411,11 +1412,44 @@ INTERCEPTOR(int, hipGraphLaunch_spt, HipGraphExec GraphExec, HipStream Stream) {
Stream);
}
+static void registerDynamicModuleFromFile(int Rc, void **Module,
+ const char *Filename) {
+ if (Rc)
+ return;
+
+ FILE *File = fopen(Filename, "rb");
+ if (!File) {
+ PROF_WARN("failed to open dynamic module file %s\n", Filename);
+ return;
+ }
+
+ if (fseek(File, 0, SEEK_END) != 0) {
+ PROF_WARN("failed to seek dynamic module file %s\n", Filename);
+ fclose(File);
+ return;
+ }
+ long FileSize = ftell(File);
+ if (FileSize <= 0 || fseek(File, 0, SEEK_SET) != 0) {
+ PROF_WARN("failed to get size of dynamic module file %s\n", Filename);
+ fclose(File);
+ return;
+ }
+
+ ManagedMemory Image;
+ lprofGetFileContentBuffer(File, (uint64_t)FileSize, &Image);
+ fclose(File);
+ if (Image.Status == MS_INVALID) {
+ PROF_WARN("failed to read dynamic module file %s\n", Filename);
+ return;
+ }
+
+ __llvm_profile_offload_register_dynamic_module(Rc, Module, Image.Addr);
+ lprofReleaseBuffer(&Image, (size_t)FileSize);
+}
+
INTERCEPTOR(int, hipModuleLoad, void **module, const char *fname) {
int rc = REAL(hipModuleLoad)(module, fname);
- /* Pass NULL image: no in-memory ELF is available for filename loads,
- * so the register hook skips symbol enumeration. */
- __llvm_profile_offload_register_dynamic_module(rc, module, nullptr);
+ registerDynamicModuleFromFile(rc, module, fname);
return rc;
}
diff --git a/compiler-rt/test/profile/AMDGPU/device-module-load-file.hip b/compiler-rt/test/profile/AMDGPU/device-module-load-file.hip
new file mode 100644
index 0000000000000..0ac7751446999
--- /dev/null
+++ b/compiler-rt/test/profile/AMDGPU/device-module-load-file.hip
@@ -0,0 +1,63 @@
+// Device PGO supports code objects loaded by filename through hipModuleLoad.
+//
+// REQUIRES: hip, amdgpu
+// UNSUPPORTED: windows
+
+// RUN: rm -rf %t.dir && mkdir -p %t.dir
+// RUN: %clang -x hip --offload-arch=%amdgpu_arch \
+// RUN: --rocm-path=%hip_lib_path/.. \
+// RUN: -fprofile-instr-generate -DBUILD_MODULE %s \
+// RUN: -o %t.dir/module -L%hip_lib_path -lamdhip64
+// RUN: cd %t.dir && llvm-objdump --offloading module
+// RUN: mv %t.dir/module.0.hip-amdgcn-amd-amdhsa--*gfx* %t.dir/module.co
+// RUN: %clang -x c++ -c %s -D__HIP_PLATFORM_AMD__ \
+// RUN: -I%hip_lib_path/../include -o %t.dir/loader.o
+// RUN: %clang %t.dir/loader.o --hip-link \
+// RUN: --rocm-path=%hip_lib_path/.. -fprofile-instr-generate \
+// RUN: -L%hip_lib_path -lamdhip64 -o %t.dir/loader
+// RUN: env LLVM_PROFILE_FILE=%t.dir/host.%%p.profraw \
+// RUN: LD_LIBRARY_PATH=%hip_lib_path:$LD_LIBRARY_PATH \
+// RUN: HIP_VISIBLE_DEVICES=0 %t.dir/loader %t.dir/module.co
+// RUN: ls %t.dir/gfx*.profraw
+// RUN: llvm-profdata merge %t.dir/*.profraw -o %t.dir/module.profdata
+// RUN: llvm-profdata show --all-functions %t.dir/module.profdata \
+// RUN: | FileCheck %s
+
+#include <hip/hip_runtime.h>
+
+#ifdef BUILD_MODULE
+
+extern "C" __global__ void module_kernel() {}
+
+int main() { return 0; }
+
+#else
+
+int main(int Argc, char **Argv) {
+ if (Argc != 2)
+ return 1;
+
+ hipModule_t Module = nullptr;
+ if (hipModuleLoad(&Module, Argv[1]) != hipSuccess)
+ return 2;
+
+ hipFunction_t Function = nullptr;
+ if (hipModuleGetFunction(&Function, Module, "module_kernel") != hipSuccess)
+ return 3;
+
+ if (hipModuleLaunchKernel(Function, 1, 1, 1, 1, 1, 1, 0, nullptr, nullptr,
+ nullptr) != hipSuccess)
+ return 4;
+ if (hipDeviceSynchronize() != hipSuccess)
+ return 5;
+ if (hipModuleUnload(Module) != hipSuccess)
+ return 6;
+ return 0;
+}
+
+#endif
+
+// CHECK: module_kernel:
+// CHECK-NEXT: Hash:
+// CHECK-NEXT: Counters: 1
+// CHECK-NEXT: Function count: 1
``````````
</details>
https://github.com/llvm/llvm-project/pull/211875
More information about the llvm-commits
mailing list