Skip to content

[PGO][HIP] Fix profile-only Windows link by gating ROCm interceptor macro - #200859

Merged
yxsamliu merged 1 commit into
llvm:mainfrom
yxsamliu:amd/dev/yaxunl/fix-profile-rocm-windows-link-main
Jun 1, 2026
Merged

[PGO][HIP] Fix profile-only Windows link by gating ROCm interceptor macro#200859
yxsamliu merged 1 commit into
llvm:mainfrom
yxsamliu:amd/dev/yaxunl/fix-profile-rocm-windows-link-main

Conversation

@yxsamliu

@yxsamliu yxsamliu commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

PR #200111 stops compiling InstrProfilingPlatformROCm.cpp (which defines the
HIP GPU helper __llvm_profile_hip_collect_device_data) in profile-only builds.
But the compile define -DCOMPILER_RT_BUILD_PROFILE_ROCM=1 was still added
whenever the COMPILER_RT_BUILD_PROFILE_ROCM option was on (the default), so
InstrProfilingFile.c still referenced the helper from __llvm_profile_write_file
even though it was never built.

On ELF the declaration is weak, so the undefined symbol folds to null and the
address-guarded call is skipped. COFF/Windows has no such fallback:

error LNK2019: unresolved external symbol
__llvm_profile_hip_collect_device_data referenced in function
__llvm_profile_write_file

Add the define only when PROFILE_HAS_HIP_INTERCEPTOR is true, i.e. the same
condition that keeps InstrProfilingPlatformROCm.cpp in the archive, so the
macro is defined iff the helper is actually compiled in.

Reported by zmodem:
#200111 (comment)

…acro

PR llvm#200111 stops compiling InstrProfilingPlatformROCm.cpp (which defines the
HIP GPU helper __llvm_profile_hip_collect_device_data) in profile-only builds.
But the compile define -DCOMPILER_RT_BUILD_PROFILE_ROCM=1 was still added
whenever the COMPILER_RT_BUILD_PROFILE_ROCM option was on (the default), so
InstrProfilingFile.c still referenced the helper from __llvm_profile_write_file
even though it was never built.

On ELF the declaration is weak, so the undefined symbol folds to null and the
address-guarded call is skipped. COFF/Windows has no such fallback:

  error LNK2019: unresolved external symbol
  __llvm_profile_hip_collect_device_data referenced in function
  __llvm_profile_write_file

Add the define only when PROFILE_HAS_HIP_INTERCEPTOR is true, i.e. the same
condition that keeps InstrProfilingPlatformROCm.cpp in the archive, so the
macro is defined iff the helper is actually compiled in.

Reported by zmodem:
llvm#200111 (comment)
@llvmorg-github-actions llvmorg-github-actions Bot added compiler-rt PGO Profile Guided Optimizations labels Jun 1, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-pgo

Author: Yaxun (Sam) Liu (yxsamliu)

Changes

PR #200111 stops compiling InstrProfilingPlatformROCm.cpp (which defines the
HIP GPU helper __llvm_profile_hip_collect_device_data) in profile-only builds.
But the compile define -DCOMPILER_RT_BUILD_PROFILE_ROCM=1 was still added
whenever the COMPILER_RT_BUILD_PROFILE_ROCM option was on (the default), so
InstrProfilingFile.c still referenced the helper from __llvm_profile_write_file
even though it was never built.

On ELF the declaration is weak, so the undefined symbol folds to null and the
address-guarded call is skipped. COFF/Windows has no such fallback:

error LNK2019: unresolved external symbol
__llvm_profile_hip_collect_device_data referenced in function
__llvm_profile_write_file

Add the define only when PROFILE_HAS_HIP_INTERCEPTOR is true, i.e. the same
condition that keeps InstrProfilingPlatformROCm.cpp in the archive, so the
macro is defined iff the helper is actually compiled in.

Reported by zmodem:
#200111 (comment)


Full diff: https://github.com/llvm/llvm-project/pull/200859.diff

1 Files Affected:

  • (modified) compiler-rt/lib/profile/CMakeLists.txt (+11-6)
diff --git a/compiler-rt/lib/profile/CMakeLists.txt b/compiler-rt/lib/profile/CMakeLists.txt
index de26177a4a2b7..77db2477bb7c6 100644
--- a/compiler-rt/lib/profile/CMakeLists.txt
+++ b/compiler-rt/lib/profile/CMakeLists.txt
@@ -158,12 +158,6 @@ if(COMPILER_RT_PROFILE_BAREMETAL)
      -DCOMPILER_RT_PROFILE_BAREMETAL=1)
 endif()
 
-if(COMPILER_RT_BUILD_PROFILE_ROCM)
-  set(EXTRA_FLAGS
-      ${EXTRA_FLAGS}
-      -DCOMPILER_RT_BUILD_PROFILE_ROCM=1)
-endif()
-
 # The HIP host interceptor in InstrProfilingPlatformROCm.cpp pulls in
 # RTInterception + sanitizer_common object libs. Those targets are only created
 # when COMPILER_RT_BUILD_SANITIZERS / _MEMPROF / _XRAY / _CTX_PROFILE is enabled
@@ -190,6 +184,17 @@ if(NOT PROFILE_HAS_HIP_INTERCEPTOR)
   list(REMOVE_ITEM PROFILE_SOURCES InstrProfilingPlatformROCm.cpp)
 endif()
 
+# Only advertise the ROCm interceptor to InstrProfilingFile.c when its
+# definition (InstrProfilingPlatformROCm.cpp) is actually compiled into the
+# archive. Otherwise InstrProfilingFile.c references
+# __llvm_profile_hip_collect_device_data with no definition; on COFF/Windows
+# there is no weak-undefined fallback, so the link fails (see PR #200111).
+if(COMPILER_RT_BUILD_PROFILE_ROCM AND PROFILE_HAS_HIP_INTERCEPTOR)
+  set(EXTRA_FLAGS
+      ${EXTRA_FLAGS}
+      -DCOMPILER_RT_BUILD_PROFILE_ROCM=1)
+endif()
+
 if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "amdgcn|nvptx")
   append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding EXTRA_FLAGS)
   append_list_if(COMPILER_RT_HAS_NOGPULIB_FLAG -nogpulib EXTRA_FLAGS)

@yxsamliu
yxsamliu requested review from jhuber6 and zmodem June 1, 2026 16:26

@jhuber6 jhuber6 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is getting a little convoluted

@yxsamliu
yxsamliu merged commit 5eca8b6 into llvm:main Jun 1, 2026
13 checks passed
@zmodem

zmodem commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Thanks!

@llvm-ci

llvm-ci commented Jun 1, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-s390x-linux running on systemz-1 while building compiler-rt at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/42/builds/8986

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'libFuzzer-s390x-default-Linux :: fuzzer-timeout.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer  /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest # RUN: at line 1
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer  /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest # RUN: at line 2
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/lib/fuzzer /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/TimeoutEmptyTest.cpp -o /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutEmptyTest
not  /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 2>&1 | FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=TimeoutTest # RUN: at line 3
+ not /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1
+ FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=TimeoutTest
not  /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/hi.txt 2>&1 | FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=SingleInputTimeoutTest # RUN: at line 12
+ not /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/hi.txt
+ FileCheck /home/uweigand/sandbox/buildbot/clang-s390x-linux/llvm/compiler-rt/test/fuzzer/fuzzer-timeout.test --check-prefix=SingleInputTimeoutTest
/home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 -timeout_exitcode=0 # RUN: at line 16
+ /home/uweigand/sandbox/buildbot/clang-s390x-linux/stage1/runtimes/runtimes-bins/compiler-rt/test/fuzzer/S390XDefaultLinuxConfig/Output/fuzzer-timeout.test.tmp-TimeoutTest -timeout=1 -timeout_exitcode=0
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1765693665
INFO: Loaded 1 modules   (13 inline 8-bit counters): 13 [0x2aa066d4e70, 0x2aa066d4e7d), 
INFO: Loaded 1 PC tables (13 PCs): 13 [0x2aa066d4e80,0x2aa066d4f50), 
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2	INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 31Mb
#3659	NEW    cov: 3 ft: 3 corp: 2/4b lim: 38 exec/s: 0 rss: 32Mb L: 3/3 MS: 2 CrossOver-InsertByte-
#3681	REDUCE cov: 3 ft: 3 corp: 2/3b lim: 38 exec/s: 0 rss: 32Mb L: 2/2 MS: 2 CrossOver-EraseBytes-
#3810	REDUCE cov: 4 ft: 4 corp: 3/4b lim: 38 exec/s: 0 rss: 32Mb L: 1/2 MS: 4 ChangeBit-ShuffleBytes-CopyPart-EraseBytes-
#3986	REDUCE cov: 5 ft: 5 corp: 4/6b lim: 38 exec/s: 0 rss: 32Mb L: 2/2 MS: 1 ChangeByte-
#4106	NEW    cov: 6 ft: 6 corp: 5/38b lim: 38 exec/s: 0 rss: 32Mb L: 32/32 MS: 5 ChangeBit-CrossOver-InsertByte-InsertRepeatedBytes-CrossOver-
#4134	REDUCE cov: 6 ft: 6 corp: 5/31b lim: 38 exec/s: 0 rss: 32Mb L: 25/25 MS: 3 ChangeBit-ChangeBit-EraseBytes-
#4154	REDUCE cov: 6 ft: 6 corp: 5/20b lim: 38 exec/s: 0 rss: 32Mb L: 14/14 MS: 5 ChangeBit-ChangeBinInt-ChangeBinInt-ShuffleBytes-EraseBytes-
#4217	REDUCE cov: 6 ft: 6 corp: 5/15b lim: 38 exec/s: 0 rss: 32Mb L: 9/9 MS: 3 ChangeBinInt-ChangeBinInt-EraseBytes-
#4478	REDUCE cov: 6 ft: 6 corp: 5/13b lim: 38 exec/s: 0 rss: 32Mb L: 7/7 MS: 1 EraseBytes-
#4691	REDUCE cov: 6 ft: 6 corp: 5/10b lim: 38 exec/s: 0 rss: 32Mb L: 4/4 MS: 3 ShuffleBytes-ChangeByte-EraseBytes-
#5362	REDUCE cov: 6 ft: 6 corp: 5/9b lim: 43 exec/s: 0 rss: 32Mb L: 3/3 MS: 1 EraseBytes-
ALARM: working on the last Unit for 1 seconds
       and the timeout value is 1 (use -timeout=N to change)
MS: 1 InsertByte-; base unit: 7b8cacf38d11022dd58be684c0c225ae9970a42c
0x48,0x69,0x21,0xc9,
Hi!\311
artifact_prefix='./'; Test unit written to ./timeout-4def7510fe576c3f0aefc418702f25d7149e5245
Base64: SGkhyQ==
==3341853== ERROR: libFuzzer: timeout after 1 seconds
AddressSanitizer:DEADLYSIGNAL
=================================================================
AddressSanitizer:DEADLYSIGNAL
=================================================================
AddressSanitizer: CHECK failed: asan_report.cpp:227 "((current_error_.kind)) == ((kErrorKindInvalid))" (0x1, 0x0) (tid=3341853)
    <empty stack>

...

zmodem added a commit that referenced this pull request Jun 3, 2026
…201416)

This broke profiling builds on Windows by switching the profile library
to link against the dynamic CRT; see discussion on the PR.

There were already a number of issues reported and fixed after this PR.
Rather than piling on the fixes (and this one may need some work),
revert back to green for now to let the project recover.

This reverts commit 5db1364.

Additionally, this reverts the followup PRs in
635e120,
2766733,
4c33844, and
5eca8b6:

"[PGO][HIP] Stop pulling ROCm.o into every PGO host link (#200101)"
"[compiler-rt][profile] Add COMPILER_RT_BUILD_PROFILE_ROCM option
(#200127)"
"[PGO][HIP] Skip ROCm interceptor in profile-only compiler-rt builds
(#200111)"
"[PGO][HIP] Fix profile-only Windows link by gating ROCm interceptor
macro (#200859)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compiler-rt PGO Profile Guided Optimizations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants