[clang] fd86339 - [LinkerWrapper] Fix AMDGPU Target-IDs linking in improper order (#207853)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 8 05:26:39 PDT 2026
Author: Joseph Huber
Date: 2026-07-08T07:26:34-05:00
New Revision: fd86339aa29c096855b9cfba4a44c539a013ba15
URL: https://github.com/llvm/llvm-project/commit/fd86339aa29c096855b9cfba4a44c539a013ba15
DIFF: https://github.com/llvm/llvm-project/commit/fd86339aa29c096855b9cfba4a44c539a013ba15.diff
LOG: [LinkerWrapper] Fix AMDGPU Target-IDs linking in improper order (#207853)
Summary:
These target IDs are supposed to be ordered from most to least specific,
but we had no such ordering. The changes basically sort the input from
least to most specific using the target-id presence, then ensures that
their entries are listed first.
Fixes: https://github.com/llvm/llvm-project/issues/207835
Added:
Modified:
clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Removed:
################################################################################
diff --git a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
index a19a11e87afdb..0e018dc3af8c9 100644
--- a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
+++ b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper.c
@@ -185,6 +185,22 @@ __attribute__((visibility("protected"), used)) int x;
// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack+.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -Wl,--no-undefined {{.*}}.o {{.*}}.o
// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack-.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// RUN: llvm-offload-binary -o %t-generic.out \
+// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx90a
+// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t-generic.o -fembed-offload-object=%t-generic.out
+// RUN: llvm-offload-binary -o %t-on.out \
+// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx90a:xnack+
+// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t-on.o -fembed-offload-object=%t-on.out
+// RUN: llvm-offload-binary -o %t-off.out \
+// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx90a:xnack-
+// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t-off.o -fembed-offload-object=%t-off.out
+// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
+// RUN: --linker-path=/usr/bin/ld %t-on.o %t-off.o %t-generic.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMD-GENERIC-MERGE
+
+// AMD-GENERIC-MERGE-NOT: -mcpu=gfx90a -Wl,--no-undefined
+// AMD-GENERIC-MERGE: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack+.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -Wl,--no-undefined {{.*}}.o {{.*}}.o
+// AMD-GENERIC-MERGE: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack-.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -Wl,--no-undefined {{.*}}.o {{.*}}.o
+
// RUN: llvm-offload-binary -o %t-lib.out \
// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=generic
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t-lib.out
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 5abda37ada7fb..0e30dfca64c60 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -1398,17 +1398,30 @@ getDeviceInput(const ArgList &Args) {
}
}
+ // Handle the most specific target-ids first so a generic input merges last.
+ llvm::stable_sort(ObjectFilesToExtract,
+ [](const OffloadFile &A, const OffloadFile &B) {
+ return A.getBinary()->getArch().count(':') >
+ B.getBinary()->getArch().count(':');
+ });
+
// Link all standard input files and update the list of symbols.
MapVector<OffloadFile::TargetID, SmallVector<OffloadFile, 0>> InputFiles;
for (OffloadFile &Binary : ObjectFilesToExtract) {
if (!Binary.getBinary())
continue;
- SmallVector<OffloadFile::TargetID> CompatibleTargets = {Binary};
+ OffloadFile::TargetID Target = Binary;
+ SmallVector<OffloadFile::TargetID> CompatibleTargets;
for (const auto &[ID, Input] : InputFiles)
- if (object::areTargetsCompatible(Binary, ID))
+ if (Target.first == ID.first &&
+ clang::isCompatibleTargetID(Target.second, ID.second))
CompatibleTargets.emplace_back(ID);
+ // Seed a new image when no existing target can provide for this input.
+ if (CompatibleTargets.empty())
+ CompatibleTargets.emplace_back(Target);
+
for (const auto &[Index, ID] : llvm::enumerate(CompatibleTargets)) {
// If another target needs this binary it must be copied instead.
if (Index == CompatibleTargets.size() - 1)
More information about the cfe-commits
mailing list