Skip to content

Commit 83daddd

Browse files
jmmartinezkzhuravl
authored andcommitted
[Comgr][Cache] Cache unbundle of compressed bundles
1 parent 6cca5f7 commit 83daddd

File tree

5 files changed

+271
-27
lines changed

5 files changed

+271
-27
lines changed

amd/comgr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ option(COMGR_BUILD_SHARED_LIBS "Build the shared library"
7373
set(SOURCES
7474
src/comgr-cache.cpp
7575
src/comgr-cache-command.cpp
76+
src/comgr-cache-bundler-command.cpp
7677
src/comgr-compiler.cpp
7778
src/comgr.cpp
7879
src/comgr-device-libs.cpp
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*******************************************************************************
2+
*
3+
* University of Illinois/NCSA
4+
* Open Source License
5+
*
6+
* Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
7+
* Modifications (c) 2018 Advanced Micro Devices, Inc.
8+
* All rights reserved.
9+
*
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* with the Software without restriction, including without limitation the
13+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14+
* sell copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
*
17+
* * Redistributions of source code must retain the above copyright notice,
18+
* this list of conditions and the following disclaimers.
19+
*
20+
* * Redistributions in binary form must reproduce the above copyright
21+
* notice, this list of conditions and the following disclaimers in the
22+
* documentation and/or other materials provided with the distribution.
23+
*
24+
* * Neither the names of the LLVM Team, University of Illinois at
25+
* Urbana-Champaign, nor the names of its contributors may be used to
26+
* endorse or promote products derived from this Software without specific
27+
* prior written permission.
28+
*
29+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+
* CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
35+
* THE SOFTWARE.
36+
*
37+
******************************************************************************/
38+
39+
#include <comgr-cache-bundler-command.h>
40+
41+
#include <clang/Driver/OffloadBundler.h>
42+
#include <llvm/BinaryFormat/Magic.h>
43+
44+
namespace COMGR {
45+
using namespace llvm;
46+
using namespace clang;
47+
48+
using SizeFieldType = uint32_t;
49+
50+
bool UnbundleCommand::canCache() const {
51+
// The header format for AR files is not the same as object files
52+
if (Kind == AMD_COMGR_DATA_KIND_AR_BUNDLE)
53+
return false;
54+
55+
StringRef InputFilename = Config.InputFileNames.front();
56+
file_magic Magic;
57+
if (identify_magic(InputFilename, Magic))
58+
return false;
59+
60+
// Check the input file magic. Handle only compressed bundles
61+
// It's not worth to cache other types of bundles
62+
return Magic == file_magic::offload_bundle_compressed;
63+
}
64+
65+
Error UnbundleCommand::writeExecuteOutput(StringRef CachedBuffer) {
66+
for (StringRef OutputFilename : Config.OutputFileNames) {
67+
SizeFieldType OutputFileSize;
68+
if (CachedBuffer.size() < sizeof(OutputFileSize))
69+
return createStringError(std::errc::invalid_argument,
70+
"Not enough bytes to read output file size");
71+
memcpy(&OutputFileSize, CachedBuffer.data(), sizeof(OutputFileSize));
72+
CachedBuffer = CachedBuffer.drop_front(sizeof(OutputFileSize));
73+
74+
if (CachedBuffer.size() < OutputFileSize)
75+
return createStringError(std::errc::invalid_argument,
76+
"Not enough bytes to read output file contents");
77+
78+
StringRef OutputFileContents = CachedBuffer.substr(0, OutputFileSize);
79+
CachedBuffer = CachedBuffer.drop_front(OutputFileSize);
80+
81+
if (Error Err = CachedCommandAdaptor::writeUniqueExecuteOutput(
82+
OutputFilename, OutputFileContents))
83+
return Err;
84+
}
85+
86+
if (!CachedBuffer.empty())
87+
return createStringError(std::errc::invalid_argument,
88+
"Bytes in cache entry not used for the output");
89+
return Error::success();
90+
}
91+
92+
Expected<StringRef> UnbundleCommand::readExecuteOutput() {
93+
size_t OutputSize = 0;
94+
for (StringRef OutputFilename : Config.OutputFileNames) {
95+
auto MaybeOneOutput =
96+
CachedCommandAdaptor::readUniqueExecuteOutput(OutputFilename);
97+
if (!MaybeOneOutput)
98+
return MaybeOneOutput.takeError();
99+
100+
const MemoryBuffer &OneOutputBuffer = **MaybeOneOutput;
101+
SizeFieldType OneOutputFileSize = OneOutputBuffer.getBufferSize();
102+
103+
OutputBuffer.resize_for_overwrite(OutputSize + sizeof(OneOutputFileSize) +
104+
OneOutputFileSize);
105+
106+
memcpy(OutputBuffer.data() + OutputSize, &OneOutputFileSize,
107+
sizeof(OneOutputFileSize));
108+
OutputSize += sizeof(OneOutputFileSize);
109+
memcpy(OutputBuffer.data() + OutputSize, OneOutputBuffer.getBufferStart(),
110+
OneOutputFileSize);
111+
OutputSize += OneOutputFileSize;
112+
}
113+
return OutputBuffer;
114+
}
115+
116+
amd_comgr_status_t UnbundleCommand::execute(raw_ostream &LogS) {
117+
assert(Config.InputFileNames.size() == 1);
118+
119+
OffloadBundler Bundler(Config);
120+
121+
switch (Kind) {
122+
case AMD_COMGR_DATA_KIND_BC_BUNDLE:
123+
case AMD_COMGR_DATA_KIND_OBJ_BUNDLE: {
124+
if (Error Err = Bundler.UnbundleFiles()) {
125+
logAllUnhandledErrors(std::move(Err), LogS, "Unbundle Error: ");
126+
return AMD_COMGR_STATUS_ERROR;
127+
}
128+
break;
129+
}
130+
case AMD_COMGR_DATA_KIND_AR_BUNDLE: {
131+
if (Error Err = Bundler.UnbundleArchive()) {
132+
logAllUnhandledErrors(std::move(Err), LogS, "Unbundle Archives Error: ");
133+
return AMD_COMGR_STATUS_ERROR;
134+
}
135+
break;
136+
}
137+
default:
138+
llvm_unreachable("invalid bundle type");
139+
}
140+
141+
return AMD_COMGR_STATUS_SUCCESS;
142+
}
143+
144+
CachedCommandAdaptor::ActionClass UnbundleCommand::getClass() const {
145+
return clang::driver::Action::OffloadUnbundlingJobClass;
146+
}
147+
148+
void UnbundleCommand::addOptionsIdentifier(HashAlgorithm &H) const {
149+
H.update(Config.TargetNames.size());
150+
for (StringRef Target : Config.TargetNames) {
151+
CachedCommandAdaptor::addString(H, Target);
152+
}
153+
}
154+
155+
Error UnbundleCommand::addInputIdentifier(HashAlgorithm &H) const {
156+
StringRef InputFilename = Config.InputFileNames.front();
157+
158+
constexpr size_t LargestHeaderSize = CompressedOffloadBundle::V2HeaderSize;
159+
160+
ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeInputBuffer =
161+
MemoryBuffer::getFileSlice(InputFilename, LargestHeaderSize, 0);
162+
if (!MaybeInputBuffer) {
163+
std::error_code EC = MaybeInputBuffer.getError();
164+
return createStringError(EC, Twine("Failed to open ") + InputFilename +
165+
" : " + EC.message() + "\n");
166+
}
167+
168+
MemoryBuffer &InputBuffer = **MaybeInputBuffer;
169+
170+
uint8_t Header[LargestHeaderSize];
171+
memset(Header, 0, sizeof(Header));
172+
memcpy(Header, InputBuffer.getBufferStart(),
173+
std::min(LargestHeaderSize, InputBuffer.getBufferSize()));
174+
175+
// only hash the input file, not the whole header. Colissions are unlikely
176+
// since the header includes a hash (weak) of the contents
177+
H.update(Header);
178+
return Error::success();
179+
}
180+
181+
} // namespace COMGR
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*******************************************************************************
2+
*
3+
* University of Illinois/NCSA
4+
* Open Source License
5+
*
6+
* Copyright (c) 2018 Advanced Micro Devices, Inc. All Rights Reserved.
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* with the Software without restriction, including without limitation the
11+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12+
* sell copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* * Redistributions of source code must retain the above copyright notice,
16+
* this list of conditions and the following disclaimers.
17+
*
18+
* * Redistributions in binary form must reproduce the above copyright
19+
* notice, this list of conditions and the following disclaimers in the
20+
* documentation and/or other materials provided with the distribution.
21+
*
22+
* * Neither the names of Advanced Micro Devices, Inc. nor the names of its
23+
* contributors may be used to endorse or promote products derived from
24+
* this Software without specific prior written permission.
25+
*
26+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29+
* CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
32+
* THE SOFTWARE.
33+
*
34+
******************************************************************************/
35+
36+
#ifndef COMGR_CACHE_BUNDLER_COMMAND_H
37+
#define COMGR_CACHE_BUNDLER_COMMAND_H
38+
39+
#include <comgr-cache-command.h>
40+
41+
namespace clang {
42+
class OffloadBundlerConfig;
43+
} // namespace clang
44+
45+
namespace COMGR {
46+
class UnbundleCommand final : public CachedCommandAdaptor {
47+
private:
48+
amd_comgr_data_kind_t Kind;
49+
const clang::OffloadBundlerConfig &Config;
50+
51+
// To avoid copies, store the output of execute, such that readExecuteOutput
52+
// can return a reference.
53+
llvm::SmallString<64> OutputBuffer;
54+
55+
public:
56+
UnbundleCommand(amd_comgr_data_kind_t Kind,
57+
const clang::OffloadBundlerConfig &Config)
58+
: Kind(Kind), Config(Config) {}
59+
60+
bool canCache() const override;
61+
llvm::Error writeExecuteOutput(llvm::StringRef CachedBuffer) override;
62+
llvm::Expected<llvm::StringRef> readExecuteOutput() override;
63+
amd_comgr_status_t execute(llvm::raw_ostream &LogS) override;
64+
65+
~UnbundleCommand() override = default;
66+
67+
protected:
68+
ActionClass getClass() const override;
69+
void addOptionsIdentifier(HashAlgorithm &) const override;
70+
llvm::Error addInputIdentifier(HashAlgorithm &) const override;
71+
};
72+
} // namespace COMGR
73+
74+
#endif

amd/comgr/src/comgr-compiler.cpp

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
******************************************************************************/
3838

3939
#include "comgr-compiler.h"
40+
#include "comgr-cache-bundler-command.h"
4041
#include "comgr-cache.h"
4142
#include "comgr-device-libs.h"
4243
#include "comgr-diagnostic-handler.h"
@@ -1245,6 +1246,7 @@ amd_comgr_status_t AMDGPUCompiler::unbundle() {
12451246
}
12461247

12471248
// Collect bitcode memory buffers from bitcodes, bundles, and archives
1249+
auto Cache = CommandCache::get(LogS);
12481250
for (auto *Input : InSet->DataObjects) {
12491251

12501252
const char *FileExtension;
@@ -1307,9 +1309,6 @@ amd_comgr_status_t AMDGPUCompiler::unbundle() {
13071309
BundlerConfig.OutputFileNames.emplace_back(OutputFilePath);
13081310
}
13091311

1310-
OffloadBundler Bundler(BundlerConfig);
1311-
1312-
// TODO: log vectors, build clang command
13131312
if (env::shouldEmitVerboseLogs()) {
13141313
LogS << "Extracting Bundle:\n"
13151314
<< "\t Unbundled Files Extension: ." << FileExtension << "\n"
@@ -1322,27 +1321,15 @@ amd_comgr_status_t AMDGPUCompiler::unbundle() {
13221321
LogS.flush();
13231322
}
13241323

1325-
switch (Input->DataKind) {
1326-
case AMD_COMGR_DATA_KIND_BC_BUNDLE: {
1327-
llvm::Error Err = Bundler.UnbundleFiles();
1328-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
1329-
"Unbundle Bitcodes Error: ");
1330-
break;
1331-
}
1332-
case AMD_COMGR_DATA_KIND_AR_BUNDLE: {
1333-
llvm::Error Err = Bundler.UnbundleArchive();
1334-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
1335-
"Unbundle Archives Error: ");
1336-
break;
1337-
}
1338-
case AMD_COMGR_DATA_KIND_OBJ_BUNDLE: {
1339-
llvm::Error Err = Bundler.UnbundleFiles();
1340-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(),
1341-
"Unbundle Objects Error: ");
1342-
break;
1343-
}
1344-
default:
1345-
llvm_unreachable("invalid bundle type");
1324+
UnbundleCommand Unbundle(Input->DataKind, BundlerConfig);
1325+
if (Cache) {
1326+
if (auto Status = Cache->execute(Unbundle, LogS)) {
1327+
return Status;
1328+
}
1329+
} else {
1330+
if (auto Status = Unbundle.execute(LogS)) {
1331+
return Status;
1332+
}
13461333
}
13471334

13481335
// Add new bitcodes to OutSetT

clang/include/clang/Driver/OffloadBundler.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,17 @@ class CompressedOffloadBundle {
113113
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
114114
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
115115
static inline const size_t HashFieldSize = sizeof(uint64_t);
116+
static inline const llvm::StringRef MagicNumber = "CCOB";
117+
static inline const uint16_t Version = 2;
118+
119+
public:
116120
static inline const size_t V1HeaderSize =
117121
MagicSize + VersionFieldSize + MethodFieldSize +
118122
UncompressedSizeFieldSize + HashFieldSize;
119123
static inline const size_t V2HeaderSize =
120124
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
121125
UncompressedSizeFieldSize + HashFieldSize;
122-
static inline const llvm::StringRef MagicNumber = "CCOB";
123-
static inline const uint16_t Version = 2;
124126

125-
public:
126127
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
127128
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
128129
bool Verbose = false);

0 commit comments

Comments
 (0)