Skip to content

Commit 9838076

Browse files
committed
[clang-offload-bundler] Make Bundle Entry ID backward compatible
Earlier BundleEntryID used to be <OffloadKind>-<Triple>-<GPUArch>. This used to work because the clang-offload-bundler didn't need GPUArch explicitly for any bundling/unbundling action. With unbundleArchive it needs GPUArch to ensure compatibility between device specific code objects. D93525 enforced triples to have separators for all 4 components irrespective of number of components, like "amdgcn-amd-amdhsa--". It was required to to correctly parse a possible 4th environment component or a GPU. But, this condition is breaking backward compatibility with archive libraries compiled with compilers older than D93525. This patch allows triples to have any number of components with and without extra separator for empty environment field. Thus, both the following bundle entry IDs are same: openmp-amdgcn-amd-amdhsa--gfx906 openmp-amdgcn-amd-amdhsa-gfx906 Reviewed By: yaxunl, grokos Differential Revision: https://reviews.llvm.org/D106809
1 parent 7fb66d4 commit 9838076

File tree

6 files changed

+73
-56
lines changed

6 files changed

+73
-56
lines changed

clang/docs/ClangOffloadBundler.rst

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,7 @@ Where:
121121
============= ==============================================================
122122

123123
**target-triple**
124-
The target triple of the code object:
125-
126-
.. code::
127-
128-
<Architecture>-<Vendor>-<OS>-<Environment>
129-
130-
It is required to have all four components present, if target-id is present.
131-
Components are hyphen separated. If a component is not specified then the
132-
empty string must be used in its place.
124+
The target triple of the code object.
133125

134126
**target-id**
135127
The canonical target ID of the code object. Present only if the target

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7686,16 +7686,12 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
76867686
});
76877687
}
76887688
Triples += Action::GetOffloadKindName(CurKind);
7689-
Triples += "-";
7690-
std::string NormalizedTriple = CurTC->getTriple().normalize();
7691-
Triples += NormalizedTriple;
7692-
7693-
if (CurDep->getOffloadingArch() != nullptr) {
7694-
// If OffloadArch is present it can only appear as the 6th hypen
7695-
// sepearated field of Bundle Entry ID. So, pad required number of
7696-
// hyphens in Triple.
7697-
for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
7698-
Triples += "-";
7689+
Triples += '-';
7690+
Triples += CurTC->getTriple().normalize();
7691+
if ((CurKind == Action::OFK_HIP || CurKind == Action::OFK_OpenMP ||
7692+
CurKind == Action::OFK_Cuda) &&
7693+
CurDep->getOffloadingArch()) {
7694+
Triples += '-';
76997695
Triples += CurDep->getOffloadingArch();
77007696
}
77017697
}
@@ -7768,17 +7764,13 @@ void OffloadBundler::ConstructJobMultipleOutputs(
77687764

77697765
auto &Dep = DepInfo[I];
77707766
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
7771-
Triples += "-";
7772-
std::string NormalizedTriple =
7773-
Dep.DependentToolChain->getTriple().normalize();
7774-
Triples += NormalizedTriple;
7775-
7776-
if (!Dep.DependentBoundArch.empty()) {
7777-
// If OffloadArch is present it can only appear as the 6th hypen
7778-
// sepearated field of Bundle Entry ID. So, pad required number of
7779-
// hyphens in Triple.
7780-
for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
7781-
Triples += "-";
7767+
Triples += '-';
7768+
Triples += Dep.DependentToolChain->getTriple().normalize();
7769+
if ((Dep.DependentOffloadKind == Action::OFK_HIP ||
7770+
Dep.DependentOffloadKind == Action::OFK_OpenMP ||
7771+
Dep.DependentOffloadKind == Action::OFK_Cuda) &&
7772+
!Dep.DependentBoundArch.empty()) {
7773+
Triples += '-';
77827774
Triples += Dep.DependentBoundArch;
77837775
}
77847776
}

clang/test/Driver/clang-offload-bundler.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,16 +382,30 @@
382382
// Check archive unbundling
383383
//
384384
// Create few code object bundles and archive them to create an input archive
385-
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx906,openmp-amdgcn-amd-amdhsa--gfx908 -inputs=%t.o,%t.tgt1,%t.tgt2 -outputs=%t.simple.bundle
385+
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa-gfx906,openmp-amdgcn-amd-amdhsa--gfx908 -inputs=%t.o,%t.tgt1,%t.tgt2 -outputs=%t.simple.bundle
386386
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-amdgcn-amd-amdhsa--gfx903 -inputs=%t.o,%t.tgt1 -outputs=%t.simple1.bundle
387387
// RUN: llvm-ar cr %t.input-archive.a %t.simple.bundle %t.simple1.bundle
388388

389-
// RUN: clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa--gfx906,openmp-amdgcn-amd-amdhsa--gfx908 -inputs=%t.input-archive.a -outputs=%t-archive-gfx906-simple.a,%t-archive-gfx908-simple.a
389+
// RUN: clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa-gfx906,openmp-amdgcn-amd-amdhsa-gfx908 -inputs=%t.input-archive.a -outputs=%t-archive-gfx906-simple.a,%t-archive-gfx908-simple.a
390390
// RUN: llvm-ar t %t-archive-gfx906-simple.a | FileCheck %s -check-prefix=GFX906
391-
// GFX906: simple-openmp-amdgcn-amd-amdhsa--gfx906
391+
// GFX906: simple-openmp-amdgcn-amd-amdhsa-gfx906
392392
// RUN: llvm-ar t %t-archive-gfx908-simple.a | FileCheck %s -check-prefix=GFX908
393393
// GFX908-NOT: {{gfx906}}
394394

395+
// Check for error if no compatible code object is found in the heterogeneous archive library
396+
// RUN: not clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa-gfx803 -inputs=%t.input-archive.a -outputs=%t-archive-gfx803-incompatible.a 2>&1 | FileCheck %s -check-prefix=INCOMPATIBLEARCHIVE
397+
// INCOMPATIBLEARCHIVE: error: no compatible code object found for the target 'openmp-amdgcn-amd-amdhsa-gfx803' in heterogeneous archive library
398+
399+
// Check creation of empty archive if allow-missing-bundles is present and no compatible code object is found in the heterogeneous archive library
400+
// RUN: clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa-gfx803 -inputs=%t.input-archive.a -outputs=%t-archive-gfx803-empty.a -allow-missing-bundles
401+
// RUN: cat %t-archive-gfx803-empty.a | FileCheck %s -check-prefix=EMPTYARCHIVE
402+
// EMPTYARCHIVE: !<arch>
403+
404+
// Tests to check compatibility between Bundle Entry ID formats i.e. between presence/absence of extra hyphen in case of missing environment field
405+
// RUN: clang-offload-bundler -unbundle -type=a -targets=openmp-amdgcn-amd-amdhsa--gfx906,openmp-amdgcn-amd-amdhsa-gfx908 -inputs=%t.input-archive.a -outputs=%t-archive-gfx906-simple.a,%t-archive-gfx908-simple.a -debug-only=CodeObjectCompatibility 2>&1 | FileCheck %s -check-prefix=BUNDLECOMPATIBILITY
406+
// BUNDLECOMPATIBILITY: Compatible: Exact match: [CodeObject: openmp-amdgcn-amd-amdhsa-gfx906] : [Target: openmp-amdgcn-amd-amdhsa--gfx906]
407+
// BUNDLECOMPATIBILITY: Compatible: Exact match: [CodeObject: openmp-amdgcn-amd-amdhsa--gfx908] : [Target: openmp-amdgcn-amd-amdhsa-gfx908]
408+
395409
// Some code so that we can create a binary out of this file.
396410
int A = 0;
397411
void test_func(void) {

clang/test/Driver/hip-rdc-device-only.hip

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
// COMMON-SAME: {{.*}} {{".*a.cu"}}
8383

8484
// COMMON: "{{.*}}clang-offload-bundler" "-type={{(bc|ll)}}"
85-
// COMMON-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
85+
// COMMON-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
8686
// COMMON-SAME: "-outputs=a-hip-amdgcn-amd-amdhsa.{{(bc|ll)}}"
8787

8888
// COMMON: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
@@ -112,7 +112,7 @@
112112
// COMMON-SAME: {{.*}} {{".*b.hip"}}
113113

114114
// COMMON: "{{.*}}clang-offload-bundler" "-type={{(bc|ll)}}"
115-
// COMMON-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
115+
// COMMON-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
116116
// COMMON-SAME: "-outputs=b-hip-amdgcn-amd-amdhsa.{{(bc|ll)}}"
117117

118118
// SAVETEMP: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu"
@@ -142,7 +142,7 @@
142142
// SAVETEMP-SAME: {{.*}} "-o" {{"a.*.ll"}} "-x" "ir" [[A_GFX900_TMP_BC]]
143143

144144
// SAVETEMP: "{{.*}}clang-offload-bundler" "-type=ll"
145-
// SAVETEMP-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
145+
// SAVETEMP-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
146146
// SAVETEMP-SAME: "-outputs=a-hip-amdgcn-amd-amdhsa.ll"
147147

148148
// SAVETEMP: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu"
@@ -172,7 +172,7 @@
172172
// SAVETEMP-SAME: {{.*}} "-o" {{"b.*.ll"}} "-x" "ir" [[B_GFX900_TMP_BC]]
173173

174174
// SAVETEMP: "{{.*}}clang-offload-bundler" "-type=ll"
175-
// SAVETEMP-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
175+
// SAVETEMP-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
176176
// SAVETEMP-SAME: "-outputs=b-hip-amdgcn-amd-amdhsa.ll"
177177

178178
// FAIL: error: cannot specify -o when generating multiple output files

clang/test/Driver/hip-toolchain-rdc-separate.hip

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
// CHECK-SAME: {{.*}} [[A_SRC]]
4545

4646
// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
47-
// CHECK-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900,host-x86_64-unknown-linux-gnu"
47+
// CHECK-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900,host-x86_64-unknown-linux-gnu"
4848
// CHECK-SAME: "-outputs=[[A_O:.*a.o]]" "-inputs=[[A_BC1]],[[A_BC2]],[[A_OBJ_HOST]]"
4949

5050
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
@@ -79,7 +79,7 @@
7979
// CHECK-SAME: {{.*}} [[B_SRC]]
8080

8181
// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
82-
// CHECK-SAME: "-targets=hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900,host-x86_64-unknown-linux-gnu"
82+
// CHECK-SAME: "-targets=hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900,host-x86_64-unknown-linux-gnu"
8383
// CHECK-SAME: "-outputs=[[B_O:.*b.o]]" "-inputs=[[B_BC1]],[[B_BC2]],[[B_OBJ_HOST]]"
8484

8585
// RUN: touch %T/a.o
@@ -91,22 +91,22 @@
9191
// RUN: 2>&1 | FileCheck -check-prefix=LINK %s
9292

9393
// LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
94-
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
94+
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
9595
// LINK-SAME: "-inputs=[[A_O:.*a.o]]" "-outputs=[[A_OBJ_HOST:.*o]],{{.*o}},{{.*o}}"
9696
// LINK: "-unbundle" "-allow-missing-bundles"
9797

9898
// LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
99-
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
99+
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
100100
// LINK-SAME: "-inputs=[[B_O:.*b.o]]" "-outputs=[[B_OBJ_HOST:.*o]],{{.*o}},{{.*o}}"
101101
// LINK: "-unbundle" "-allow-missing-bundles"
102102

103103
// LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
104-
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
104+
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
105105
// LINK-SAME: "-inputs=[[A_O]]" "-outputs={{.*o}},[[A_BC1:.*o]],[[A_BC2:.*o]]"
106106
// LINK: "-unbundle" "-allow-missing-bundles"
107107

108108
// LINK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
109-
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx803,hip-amdgcn-amd-amdhsa--gfx900"
109+
// LINK-SAME: "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
110110
// LINK-SAME: "-inputs=[[B_O]]" "-outputs={{.*o}},[[B_BC1:.*o]],[[B_BC2:.*o]]"
111111
// LINK: "-unbundle" "-allow-missing-bundles"
112112

clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
///
1515
//===----------------------------------------------------------------------===//
1616

17+
#include "clang/Basic/Cuda.h"
1718
#include "clang/Basic/Version.h"
1819
#include "llvm/ADT/ArrayRef.h"
1920
#include "llvm/ADT/SmallString.h"
@@ -134,21 +135,28 @@ static std::string BundlerExecutable;
134135
/// * Offload Kind - Host, OpenMP, or HIP
135136
/// * Triple - Standard LLVM Triple
136137
/// * GPUArch (Optional) - Processor name, like gfx906 or sm_30
137-
/// In presence of Proc, the Triple should contain separator "-" for all
138-
/// standard four components, even if they are empty.
138+
139139
struct OffloadTargetInfo {
140140
StringRef OffloadKind;
141141
llvm::Triple Triple;
142142
StringRef GPUArch;
143143

144144
OffloadTargetInfo(const StringRef Target) {
145-
SmallVector<StringRef, 6> Components;
146-
Target.split(Components, '-', 5);
147-
Components.resize(6);
148-
this->OffloadKind = Components[0];
149-
this->Triple = llvm::Triple(Components[1], Components[2], Components[3],
150-
Components[4]);
151-
this->GPUArch = Components[5];
145+
auto TargetFeatures = Target.split(':');
146+
auto TripleOrGPU = TargetFeatures.first.rsplit('-');
147+
148+
if (clang::StringToCudaArch(TripleOrGPU.second) !=
149+
clang::CudaArch::UNKNOWN) {
150+
auto KindTriple = TripleOrGPU.first.split('-');
151+
this->OffloadKind = KindTriple.first;
152+
this->Triple = llvm::Triple(KindTriple.second);
153+
this->GPUArch = Target.substr(Target.find(TripleOrGPU.second));
154+
} else {
155+
auto KindTriple = TargetFeatures.first.split('-');
156+
this->OffloadKind = KindTriple.first;
157+
this->Triple = llvm::Triple(KindTriple.second);
158+
this->GPUArch = "";
159+
}
152160
}
153161

154162
bool hasHostKind() const { return this->OffloadKind == "host"; }
@@ -1063,9 +1071,10 @@ bool isCodeObjectCompatible(OffloadTargetInfo &CodeObjectInfo,
10631071

10641072
// Compatible in case of exact match.
10651073
if (CodeObjectInfo == TargetInfo) {
1066-
DEBUG_WITH_TYPE(
1067-
"CodeObjectCompatibility",
1068-
dbgs() << "Compatible: Exact match: " << CodeObjectInfo.str() << "\n");
1074+
DEBUG_WITH_TYPE("CodeObjectCompatibility",
1075+
dbgs() << "Compatible: Exact match: \t[CodeObject: "
1076+
<< CodeObjectInfo.str()
1077+
<< "]\t:\t[Target: " << TargetInfo.str() << "]\n");
10691078
return true;
10701079
}
10711080

@@ -1276,9 +1285,19 @@ static Error UnbundleArchive() {
12761285
} else if (!AllowMissingBundles) {
12771286
std::string ErrMsg =
12781287
Twine("no compatible code object found for the target '" + Target +
1279-
"' in heterogenous archive library: " + IFName)
1288+
"' in heterogeneous archive library: " + IFName)
12801289
.str();
12811290
return createStringError(inconvertibleErrorCode(), ErrMsg);
1291+
} else { // Create an empty archive file if no compatible code object is
1292+
// found and "allow-missing-bundles" is enabled. It ensures that
1293+
// the linker using output of this step doesn't complain about
1294+
// the missing input file.
1295+
std::vector<llvm::NewArchiveMember> EmptyArchive;
1296+
EmptyArchive.clear();
1297+
if (Error WriteErr = writeArchive(FileName, EmptyArchive, true,
1298+
getDefaultArchiveKindForHost(), true,
1299+
false, nullptr))
1300+
return WriteErr;
12821301
}
12831302
}
12841303

0 commit comments

Comments
 (0)