@@ -50,14 +50,14 @@ static cl::opt<std::string> BaseOutputFilename{
50
50
// with prodced IR modules files names.
51
51
static cl::opt<std::string> OutputIRFilesList{
52
52
" 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)};
54
54
55
55
// Module splitter produces multiple TXT files. These files contain kernel names
56
56
// list presented in a produced module. TXT files list is a file list
57
57
// with produced TXT files names.
58
58
static cl::opt<std::string> OutputTxtFilesList{
59
59
" 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)};
61
61
62
62
static cl::opt<bool > Force{" f" , cl::desc (" Enable binary output on terminals" ),
63
63
cl::cat (ExtractCat)};
@@ -88,45 +88,62 @@ static void writeToFile(std::string Filename, std::string Content) {
88
88
OS.close ();
89
89
}
90
90
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) {
93
97
for (auto &F : M.functions ()) {
94
98
if (F.getCallingConv () == CallingConv::SPIR_KERNEL) {
95
99
if (OneKernelPerModule) {
96
- ResKernelsSet [F.getName ()].push_back (&F);
100
+ ResKernelModuleMap [F.getName ()].push_back (&F);
97
101
} else if (F.hasFnAttribute (" sycl-module-id" )) {
98
102
auto Id = F.getFnAttribute (" sycl-module-id" );
99
103
auto Val = Id.getValueAsString ();
100
- ResKernelsSet [Val].push_back (&F);
104
+ ResKernelModuleMap [Val].push_back (&F);
101
105
}
102
106
}
103
107
}
104
108
}
105
109
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.
114
135
static void
115
136
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) {
120
140
// For each group of kernels collect all dependencies.
121
141
SetVector<GlobalValue *> GVs;
122
142
std::vector<llvm::Function *> Workqueue;
123
- std::string SymbolsList;
124
143
125
144
for (auto &F : It.second ) {
126
145
GVs.insert (F);
127
146
Workqueue.push_back (F);
128
- SymbolsList =
129
- (Twine (SymbolsList) + Twine (F->getName ()) + Twine (" \n " )).str ();
130
147
}
131
148
132
149
while (!Workqueue.empty ()) {
@@ -184,22 +201,17 @@ splitModule(Module &M,
184
201
185
202
// Save results.
186
203
ResModules.push_back (std::move (MClone));
187
- ResSymbolsLists.push_back (std::move (SymbolsList));
188
204
}
189
205
}
190
206
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) {
197
211
std::string IRFilesList;
198
- std::string TxtFilesList;
199
212
for (size_t I = 0 ; I < ResModules.size (); ++I) {
200
213
std::error_code EC;
201
- std::string CurOutFileName = BaseOutputFilename + " _" +
202
- std::to_string (NumOfFile) +
214
+ std::string CurOutFileName = BaseOutputFilename + " _" + std::to_string (I) +
203
215
((OutputAssembly) ? " .ll" : " .bc" );
204
216
205
217
raw_fd_ostream Out{CurOutFileName, EC, sys::fs::OF_None};
@@ -214,33 +226,36 @@ static void saveResults(std::vector<std::unique_ptr<Module>> &ResModules,
214
226
PrintModule.add (createBitcodeWriterPass (Out));
215
227
PrintModule.run (*ResModules[I].get ());
216
228
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 ();
228
232
}
229
233
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 ()) {
233
235
// Just pass input module to next tools if there was nothing to split.
234
236
if (IRFilesList.empty ())
235
- IRFilesList =
236
- (Twine (InputFilename) + Twine (" \n " )).str ();
237
+ IRFilesList = (Twine (InputFilename) + Twine (" \n " )).str ();
237
238
writeToFile (OutputIRFilesList, IRFilesList);
238
239
}
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 ()) {
242
257
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.
244
259
std::string TempFileNameBase = sys::path::stem (BaseOutputFilename);
245
260
SmallString<128 > Path;
246
261
std::error_code EC =
@@ -290,17 +305,32 @@ int main(int argc, char **argv) {
290
305
291
306
std::map<std::string, std::vector<Function *>> GlobalsSet;
292
307
293
- collectKernelsSet (*M.get (), GlobalsSet);
308
+ collectKernelModuleMap (*M.get (), GlobalsSet);
294
309
295
310
std::vector<std::unique_ptr<Module>> ResultModules;
296
311
std::vector<std::string> ResultSymbolsLists;
297
312
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;
299
321
300
322
if (BaseOutputFilename == " -" )
301
323
BaseOutputFilename = " a.out" ;
302
324
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
+ }
304
334
305
335
return 0 ;
306
336
}
0 commit comments