Skip to content

Commit 160684d

Browse files
Fznamznonbader
authored andcommitted
[SYCL] Separate jobs in sycl-post-link tool (#854)
Clang driver will invoke sycl-post-link twice: one time for IR module split and one time for entries list generation. This patch makes possible do not perform same job twice in this case. Signed-off-by: Mariya Podchishchaeva <[email protected]>
1 parent e6accbb commit 160684d

File tree

1 file changed

+84
-54
lines changed

1 file changed

+84
-54
lines changed

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ static cl::opt<std::string> BaseOutputFilename{
5050
// with prodced IR modules files names.
5151
static cl::opt<std::string> OutputIRFilesList{
5252
"ir-files-list", cl::desc("Specify output filename for IR files list"),
53-
cl::value_desc("filename"), cl::init("-"), cl::cat(ExtractCat)};
53+
cl::value_desc("filename"), cl::init(""), cl::cat(ExtractCat)};
5454

5555
// Module splitter produces multiple TXT files. These files contain kernel names
5656
// list presented in a produced module. TXT files list is a file list
5757
// with produced TXT files names.
5858
static cl::opt<std::string> OutputTxtFilesList{
5959
"txt-files-list", cl::desc("Specify output filename for txt files list"),
60-
cl::value_desc("filename"), cl::init("-"), cl::cat(ExtractCat)};
60+
cl::value_desc("filename"), cl::init(""), cl::cat(ExtractCat)};
6161

6262
static cl::opt<bool> Force{"f", cl::desc("Enable binary output on terminals"),
6363
cl::cat(ExtractCat)};
@@ -88,45 +88,62 @@ static void writeToFile(std::string Filename, std::string Content) {
8888
OS.close();
8989
}
9090

91-
static void collectKernelsSet(
92-
Module &M, std::map<std::string, std::vector<Function *>> &ResKernelsSet) {
91+
// Output parameter ResKernelModuleMap is a map containing groups of kernels
92+
// with same values of the sycl-module-id attribute.
93+
// The function fills ResKernelModuleMap using input module M.
94+
static void collectKernelModuleMap(
95+
Module &M,
96+
std::map<std::string, std::vector<Function *>> &ResKernelModuleMap) {
9397
for (auto &F : M.functions()) {
9498
if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
9599
if (OneKernelPerModule) {
96-
ResKernelsSet[F.getName()].push_back(&F);
100+
ResKernelModuleMap[F.getName()].push_back(&F);
97101
} else if (F.hasFnAttribute("sycl-module-id")) {
98102
auto Id = F.getFnAttribute("sycl-module-id");
99103
auto Val = Id.getValueAsString();
100-
ResKernelsSet[Val].push_back(&F);
104+
ResKernelModuleMap[Val].push_back(&F);
101105
}
102106
}
103107
}
104108
}
105109

106-
// Splits input LLVM IR module M into smaller ones.
107-
// Input parameter KernelsSet is a map containing groups of kernels with same
108-
// values in the sycl-module-id attribute. For each group of kernels a separate
109-
// IR module will be produced.
110-
// ResModules and ResSymbolsLists are output parameters.
111-
// Result modules are stored into
112-
// ResModules vector. For each result module set of kernel names is collected.
113-
// Sets of kernel names are stored into ResSymbolsLists.
110+
// Input parameter KernelModuleMap is a map containing groups of kernels with
111+
// same values of the sycl-module-id attribute. ResSymbolsLists is a vector of
112+
// kernel name lists. Each vector element is a string with kernel names from the
113+
// same module separated by \n.
114+
// The function saves names of kernels from one group to a single std::string
115+
// and stores this string to the ResSymbolsLists vector.
116+
static void collectSymbolsLists(
117+
std::map<std::string, std::vector<Function *>> &KernelModuleMap,
118+
std::vector<std::string> &ResSymbolsLists) {
119+
for (auto &It : KernelModuleMap) {
120+
std::string SymbolsList;
121+
for (auto &F : It.second) {
122+
SymbolsList =
123+
(Twine(SymbolsList) + Twine(F->getName()) + Twine("\n")).str();
124+
}
125+
ResSymbolsLists.push_back(std::move(SymbolsList));
126+
}
127+
}
128+
129+
// Input parameter KernelModuleMap is a map containing groups of kernels with
130+
// same values of the sycl-module-id attribute. For each group of kernels a
131+
// separate IR module will be produced.
132+
// ResModules is a vector of produced modules.
133+
// The function splits input LLVM IR module M into smaller ones and stores them
134+
// to the ResModules vector.
114135
static void
115136
splitModule(Module &M,
116-
std::map<std::string, std::vector<Function *>> &KernelsSet,
117-
std::vector<std::unique_ptr<Module>> &ResModules,
118-
std::vector<std::string> &ResSymbolsLists) {
119-
for (auto &It : KernelsSet) {
137+
std::map<std::string, std::vector<Function *>> &KernelModuleMap,
138+
std::vector<std::unique_ptr<Module>> &ResModules) {
139+
for (auto &It : KernelModuleMap) {
120140
// For each group of kernels collect all dependencies.
121141
SetVector<GlobalValue *> GVs;
122142
std::vector<llvm::Function *> Workqueue;
123-
std::string SymbolsList;
124143

125144
for (auto &F : It.second) {
126145
GVs.insert(F);
127146
Workqueue.push_back(F);
128-
SymbolsList =
129-
(Twine(SymbolsList) + Twine(F->getName()) + Twine("\n")).str();
130147
}
131148

132149
while (!Workqueue.empty()) {
@@ -184,22 +201,17 @@ splitModule(Module &M,
184201

185202
// Save results.
186203
ResModules.push_back(std::move(MClone));
187-
ResSymbolsLists.push_back(std::move(SymbolsList));
188204
}
189205
}
190206

191-
// Saves specified collections of llvm IR modules and corresponding lists of
192-
// kernel names to files. Saves IR files list and TXT files list if user
193-
// specified corresponding filenames.
194-
static void saveResults(std::vector<std::unique_ptr<Module>> &ResModules,
195-
std::vector<std::string> &ResSymbolsLists) {
196-
int NumOfFile = 0;
207+
// Saves specified collection of llvm IR modules to files.
208+
// Saves file list if user specified corresponding filename.
209+
static void
210+
saveResultModules(std::vector<std::unique_ptr<Module>> &ResModules) {
197211
std::string IRFilesList;
198-
std::string TxtFilesList;
199212
for (size_t I = 0; I < ResModules.size(); ++I) {
200213
std::error_code EC;
201-
std::string CurOutFileName = BaseOutputFilename + "_" +
202-
std::to_string(NumOfFile) +
214+
std::string CurOutFileName = BaseOutputFilename + "_" + std::to_string(I) +
203215
((OutputAssembly) ? ".ll" : ".bc");
204216

205217
raw_fd_ostream Out{CurOutFileName, EC, sys::fs::OF_None};
@@ -214,33 +226,36 @@ static void saveResults(std::vector<std::unique_ptr<Module>> &ResModules,
214226
PrintModule.add(createBitcodeWriterPass(Out));
215227
PrintModule.run(*ResModules[I].get());
216228

217-
IRFilesList =
218-
(Twine(IRFilesList) + Twine(CurOutFileName) + Twine("\n")).str();
219-
220-
CurOutFileName =
221-
BaseOutputFilename + "_" + std::to_string(NumOfFile) + ".txt";
222-
writeToFile(CurOutFileName, ResSymbolsLists[I]);
223-
224-
TxtFilesList =
225-
(Twine(TxtFilesList) + Twine(CurOutFileName) + Twine("\n")).str();
226-
227-
++NumOfFile;
229+
if (!OutputIRFilesList.empty())
230+
IRFilesList =
231+
(Twine(IRFilesList) + Twine(CurOutFileName) + Twine("\n")).str();
228232
}
229233

230-
if (OutputIRFilesList != "-") {
231-
// TODO: Figure out what can be added to the output list if there are no
232-
// kernels in the input module.
234+
if (!OutputIRFilesList.empty()) {
233235
// Just pass input module to next tools if there was nothing to split.
234236
if (IRFilesList.empty())
235-
IRFilesList =
236-
(Twine(InputFilename) + Twine("\n")).str();
237+
IRFilesList = (Twine(InputFilename) + Twine("\n")).str();
237238
writeToFile(OutputIRFilesList, IRFilesList);
238239
}
239-
if (OutputTxtFilesList != "-") {
240-
// TODO: Figure out what can be added to output list if there are no kernels
241-
// in the input module.
240+
}
241+
242+
// Saves specified collection of symbols lists to files.
243+
// Saves file list if user specified corresponding filename.
244+
static void saveResultSymbolsLists(std::vector<std::string> &ResSymbolsLists) {
245+
std::string TxtFilesList;
246+
for (size_t I = 0; I < ResSymbolsLists.size(); ++I) {
247+
std::string CurOutFileName =
248+
BaseOutputFilename + "_" + std::to_string(I) + ".txt";
249+
writeToFile(CurOutFileName, ResSymbolsLists[I]);
250+
251+
if (!OutputTxtFilesList.empty())
252+
TxtFilesList =
253+
(Twine(TxtFilesList) + Twine(CurOutFileName) + Twine("\n")).str();
254+
}
255+
256+
if (!OutputTxtFilesList.empty()) {
242257
if (TxtFilesList.empty()) {
243-
// Just create an empty temporary file if there was nothing to split
258+
// Just create an empty temporary file if there was nothing to split.
244259
std::string TempFileNameBase = sys::path::stem(BaseOutputFilename);
245260
SmallString<128> Path;
246261
std::error_code EC =
@@ -290,17 +305,32 @@ int main(int argc, char **argv) {
290305

291306
std::map<std::string, std::vector<Function *>> GlobalsSet;
292307

293-
collectKernelsSet(*M.get(), GlobalsSet);
308+
collectKernelModuleMap(*M.get(), GlobalsSet);
294309

295310
std::vector<std::unique_ptr<Module>> ResultModules;
296311
std::vector<std::string> ResultSymbolsLists;
297312

298-
splitModule(*M.get(), GlobalsSet, ResultModules, ResultSymbolsLists);
313+
// Default usage model of that the tool is
314+
// calling it twice with the same input due clang driver limitations.
315+
// It should not bring much extra overhead because
316+
// parseIRFile and collectKernelModuleMap functions are small (would be good
317+
// to estimate) compared to splitModule and saveResultModules.
318+
bool NoLists = OutputIRFilesList.empty() && OutputTxtFilesList.empty();
319+
bool PerformSplit = !OutputIRFilesList.empty() || NoLists;
320+
bool CollectSymbols = !OutputTxtFilesList.empty() || NoLists;
299321

300322
if (BaseOutputFilename == "-")
301323
BaseOutputFilename = "a.out";
302324

303-
saveResults(ResultModules, ResultSymbolsLists);
325+
if (PerformSplit) {
326+
splitModule(*M.get(), GlobalsSet, ResultModules);
327+
saveResultModules(ResultModules);
328+
}
329+
330+
if (CollectSymbols) {
331+
collectSymbolsLists(GlobalsSet, ResultSymbolsLists);
332+
saveResultSymbolsLists(ResultSymbolsLists);
333+
}
304334

305335
return 0;
306336
}

0 commit comments

Comments
 (0)