From 4ca610478f123df58a044378d24d43942dc93af3 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Wed, 20 Nov 2019 18:00:35 +0300 Subject: [PATCH 1/5] [SYCL] Separate jobs in sycl-post-link tool 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 --- llvm/tools/sycl-post-link/sycl-post-link.cpp | 100 +++++++++++-------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index 73f40d364a61a..1f51505f87d21 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -50,14 +50,14 @@ static cl::opt BaseOutputFilename{ // with prodced IR modules files names. static cl::opt OutputIRFilesList{ "ir-files-list", cl::desc("Specify output filename for IR files list"), - cl::value_desc("filename"), cl::init("-"), cl::cat(ExtractCat)}; + cl::value_desc("filename"), cl::init(""), cl::cat(ExtractCat)}; // Module splitter produces multiple TXT files. These files contain kernel names // list presented in a produced module. TXT files list is a file list // with produced TXT files names. static cl::opt OutputTxtFilesList{ "txt-files-list", cl::desc("Specify output filename for txt files list"), - cl::value_desc("filename"), cl::init("-"), cl::cat(ExtractCat)}; + cl::value_desc("filename"), cl::init(""), cl::cat(ExtractCat)}; static cl::opt Force{"f", cl::desc("Enable binary output on terminals"), cl::cat(ExtractCat)}; @@ -103,30 +103,41 @@ static void collectKernelsSet( } } +// Input parameter KernelsSet is a map containing groups of kernels with same +// values in the sycl-module-id attribute. +// ResSymbolsLists vector is output parameter. +// Collects set of kernel names for each group of kernels. +static void collectSymbolsLists( + std::map> &KernelsSet, + std::vector &ResSymbolsLists) { + for (auto &It : KernelsSet) { + std::string SymbolsList; + for (auto &F : It.second) { + SymbolsList = + (Twine(SymbolsList) + Twine(F->getName()) + Twine("\n")).str(); + } + ResSymbolsLists.push_back(std::move(SymbolsList)); + } +} + // Splits input LLVM IR module M into smaller ones. // Input parameter KernelsSet is a map containing groups of kernels with same // values in the sycl-module-id attribute. For each group of kernels a separate // IR module will be produced. -// ResModules and ResSymbolsLists are output parameters. -// Result modules are stored into -// ResModules vector. For each result module set of kernel names is collected. -// Sets of kernel names are stored into ResSymbolsLists. +// ResModules is output parameter. +// Result modules are stored into ResModules vector. static void splitModule(Module &M, std::map> &KernelsSet, - std::vector> &ResModules, - std::vector &ResSymbolsLists) { + std::vector> &ResModules) { for (auto &It : KernelsSet) { // For each group of kernels collect all dependencies. SetVector GVs; std::vector Workqueue; - std::string SymbolsList; for (auto &F : It.second) { GVs.insert(F); Workqueue.push_back(F); - SymbolsList = - (Twine(SymbolsList) + Twine(F->getName()) + Twine("\n")).str(); } while (!Workqueue.empty()) { @@ -184,22 +195,17 @@ splitModule(Module &M, // Save results. ResModules.push_back(std::move(MClone)); - ResSymbolsLists.push_back(std::move(SymbolsList)); } } -// Saves specified collections of llvm IR modules and corresponding lists of -// kernel names to files. Saves IR files list and TXT files list if user -// specified corresponding filenames. -static void saveResults(std::vector> &ResModules, - std::vector &ResSymbolsLists) { - int NumOfFile = 0; +// Saves specified collection of llvm IR modules. +// Saves file list if user specified corresponding filename. +static void saveResultModules(std::vector> &ResModules) { std::string IRFilesList; - std::string TxtFilesList; for (size_t I = 0; I < ResModules.size(); ++I) { std::error_code EC; std::string CurOutFileName = BaseOutputFilename + "_" + - std::to_string(NumOfFile) + + std::to_string(I) + ((OutputAssembly) ? ".ll" : ".bc"); raw_fd_ostream Out{CurOutFileName, EC, sys::fs::OF_None}; @@ -214,33 +220,37 @@ static void saveResults(std::vector> &ResModules, PrintModule.add(createBitcodeWriterPass(Out)); PrintModule.run(*ResModules[I].get()); - IRFilesList = - (Twine(IRFilesList) + Twine(CurOutFileName) + Twine("\n")).str(); - - CurOutFileName = - BaseOutputFilename + "_" + std::to_string(NumOfFile) + ".txt"; - writeToFile(CurOutFileName, ResSymbolsLists[I]); - - TxtFilesList = - (Twine(TxtFilesList) + Twine(CurOutFileName) + Twine("\n")).str(); - - ++NumOfFile; + if (!OutputIRFilesList.empty()) + IRFilesList = + (Twine(IRFilesList) + Twine(CurOutFileName) + Twine("\n")).str(); } - if (OutputIRFilesList != "-") { - // TODO: Figure out what can be added to the output list if there are no - // kernels in the input module. + if (!OutputIRFilesList.empty()) { // Just pass input module to next tools if there was nothing to split. if (IRFilesList.empty()) IRFilesList = (Twine(InputFilename) + Twine("\n")).str(); writeToFile(OutputIRFilesList, IRFilesList); } - if (OutputTxtFilesList != "-") { - // TODO: Figure out what can be added to output list if there are no kernels - // in the input module. +} + +// Saves specified collection of symbols lists. +// Saves file list if user specified corresponding filename. +static void saveResultSymbolsLists(std::vector &ResSymbolsLists) { + std::string TxtFilesList; + for (size_t I = 0; I < ResSymbolsLists.size(); ++I) { + std::string CurOutFileName = + BaseOutputFilename + "_" + std::to_string(I) + ".txt"; + writeToFile(CurOutFileName, ResSymbolsLists[I]); + + if (!OutputTxtFilesList.empty()) + TxtFilesList = + (Twine(TxtFilesList) + Twine(CurOutFileName) + Twine("\n")).str(); + } + + if (!OutputTxtFilesList.empty()) { if (TxtFilesList.empty()) { - // Just create an empty temporary file if there was nothing to split + // Just create an empty temporary file if there was nothing to split. std::string TempFileNameBase = sys::path::stem(BaseOutputFilename); SmallString<128> Path; std::error_code EC = @@ -295,12 +305,22 @@ int main(int argc, char **argv) { std::vector> ResultModules; std::vector ResultSymbolsLists; - splitModule(*M.get(), GlobalsSet, ResultModules, ResultSymbolsLists); + bool NoLists = OutputIRFilesList.empty() && OutputTxtFilesList.empty(); + bool PerformSplit = !OutputIRFilesList.empty() || NoLists; + bool CollectSymbols = !OutputTxtFilesList.empty() || NoLists; if (BaseOutputFilename == "-") BaseOutputFilename = "a.out"; - saveResults(ResultModules, ResultSymbolsLists); + if (PerformSplit) { + splitModule(*M.get(), GlobalsSet, ResultModules); + saveResultModules(ResultModules); + } + + if (CollectSymbols) { + collectSymbolsLists(GlobalsSet, ResultSymbolsLists); + saveResultSymbolsLists(ResultSymbolsLists); + } return 0; } From f17fbd991c699e805971816bc574429b5b866801 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Wed, 27 Nov 2019 15:22:20 +0300 Subject: [PATCH 2/5] Apply review comments Signed-off-by: Mariya Podchishchaeva --- llvm/tools/sycl-post-link/sycl-post-link.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index 1f51505f87d21..ade28bd028042 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -305,6 +305,11 @@ int main(int argc, char **argv) { std::vector> ResultModules; std::vector ResultSymbolsLists; + // Default usage model of that the tool is + // calling it twice with the same input due clang driver limitations. + // It should not bring much extra overhead because + // parseIRFile and collectKernelsSet functions are small (would be good to + // estimate) compared to splitModule and saveResultModules. bool NoLists = OutputIRFilesList.empty() && OutputTxtFilesList.empty(); bool PerformSplit = !OutputIRFilesList.empty() || NoLists; bool CollectSymbols = !OutputTxtFilesList.empty() || NoLists; From 841d499695ff0d80f1d07f37f5e25c55e5760769 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Fri, 29 Nov 2019 10:07:21 +0300 Subject: [PATCH 3/5] Apply CR comments Signed-off-by: Mariya Podchishchaeva --- llvm/tools/sycl-post-link/sycl-post-link.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index ade28bd028042..5986f8d4c5a39 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -103,10 +103,12 @@ static void collectKernelsSet( } } -// Input parameter KernelsSet is a map containing groups of kernels with same -// values in the sycl-module-id attribute. -// ResSymbolsLists vector is output parameter. -// Collects set of kernel names for each group of kernels. +// Input parameter KernelModuleMap is a map containing groups of kernels with +// same values of the sycl-module-id attribute. ResSymbolsLists is a vector of +// kernel name lists. Each vector element is a string with kernel names from the +// same module separated by \n. +// The function saves names of kernels from one group to a single std::string +// and stores this string to the ResSymbolsLists vector. static void collectSymbolsLists( std::map> &KernelsSet, std::vector &ResSymbolsLists) { From c6b563b38357ea6711a5273a22ccf4ebbc66daff Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Fri, 29 Nov 2019 10:18:27 +0300 Subject: [PATCH 4/5] KernelsSet -> KernelModuleMap. Improve comments. Signed-off-by: Mariya Podchishchaeva --- llvm/tools/sycl-post-link/sycl-post-link.cpp | 39 +++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index 5986f8d4c5a39..3432fdd67672a 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -88,16 +88,19 @@ static void writeToFile(std::string Filename, std::string Content) { OS.close(); } -static void collectKernelsSet( - Module &M, std::map> &ResKernelsSet) { +// Output parameter ResKernelModuleMap is a map containing groups of kernels +// with same values of the sycl-module-id attribute. +// The function fills ResKernelModuleMap using input module M. +static void collectKernelModuleMap( + Module &M, std::map> &ResKernelModuleMap) { for (auto &F : M.functions()) { if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { if (OneKernelPerModule) { - ResKernelsSet[F.getName()].push_back(&F); + ResKernelModuleMap[F.getName()].push_back(&F); } else if (F.hasFnAttribute("sycl-module-id")) { auto Id = F.getFnAttribute("sycl-module-id"); auto Val = Id.getValueAsString(); - ResKernelsSet[Val].push_back(&F); + ResKernelModuleMap[Val].push_back(&F); } } } @@ -110,9 +113,9 @@ static void collectKernelsSet( // The function saves names of kernels from one group to a single std::string // and stores this string to the ResSymbolsLists vector. static void collectSymbolsLists( - std::map> &KernelsSet, + std::map> &KernelModuleMap, std::vector &ResSymbolsLists) { - for (auto &It : KernelsSet) { + for (auto &It : KernelModuleMap) { std::string SymbolsList; for (auto &F : It.second) { SymbolsList = @@ -122,17 +125,17 @@ static void collectSymbolsLists( } } -// Splits input LLVM IR module M into smaller ones. -// Input parameter KernelsSet is a map containing groups of kernels with same -// values in the sycl-module-id attribute. For each group of kernels a separate -// IR module will be produced. -// ResModules is output parameter. -// Result modules are stored into ResModules vector. +// Input parameter KernelModuleMap is a map containing groups of kernels with +// same values of the sycl-module-id attribute. For each group of kernels a +// separate IR module will be produced. +// ResModules is a vector of produced modules. +// The function splits input LLVM IR module M into smaller ones and stores them +// to the ResModules vector. static void splitModule(Module &M, - std::map> &KernelsSet, + std::map> &KernelModuleMap, std::vector> &ResModules) { - for (auto &It : KernelsSet) { + for (auto &It : KernelModuleMap) { // For each group of kernels collect all dependencies. SetVector GVs; std::vector Workqueue; @@ -200,7 +203,7 @@ splitModule(Module &M, } } -// Saves specified collection of llvm IR modules. +// Saves specified collection of llvm IR modules to files. // Saves file list if user specified corresponding filename. static void saveResultModules(std::vector> &ResModules) { std::string IRFilesList; @@ -236,7 +239,7 @@ static void saveResultModules(std::vector> &ResModules) } } -// Saves specified collection of symbols lists. +// Saves specified collection of symbols lists to files. // Saves file list if user specified corresponding filename. static void saveResultSymbolsLists(std::vector &ResSymbolsLists) { std::string TxtFilesList; @@ -302,7 +305,7 @@ int main(int argc, char **argv) { std::map> GlobalsSet; - collectKernelsSet(*M.get(), GlobalsSet); + collectKernelModuleMap(*M.get(), GlobalsSet); std::vector> ResultModules; std::vector ResultSymbolsLists; @@ -310,7 +313,7 @@ int main(int argc, char **argv) { // Default usage model of that the tool is // calling it twice with the same input due clang driver limitations. // It should not bring much extra overhead because - // parseIRFile and collectKernelsSet functions are small (would be good to + // parseIRFile and collectKernelModuleMap functions are small (would be good to // estimate) compared to splitModule and saveResultModules. bool NoLists = OutputIRFilesList.empty() && OutputTxtFilesList.empty(); bool PerformSplit = !OutputIRFilesList.empty() || NoLists; From 79720fd7e642b3f3f68105dd306c35777db31a70 Mon Sep 17 00:00:00 2001 From: Mariya Podchishchaeva Date: Fri, 29 Nov 2019 10:19:56 +0300 Subject: [PATCH 5/5] Apply clang-format Signed-off-by: Mariya Podchishchaeva --- llvm/tools/sycl-post-link/sycl-post-link.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/tools/sycl-post-link/sycl-post-link.cpp b/llvm/tools/sycl-post-link/sycl-post-link.cpp index 3432fdd67672a..d6232473d9a6e 100644 --- a/llvm/tools/sycl-post-link/sycl-post-link.cpp +++ b/llvm/tools/sycl-post-link/sycl-post-link.cpp @@ -92,7 +92,8 @@ static void writeToFile(std::string Filename, std::string Content) { // with same values of the sycl-module-id attribute. // The function fills ResKernelModuleMap using input module M. static void collectKernelModuleMap( - Module &M, std::map> &ResKernelModuleMap) { + Module &M, + std::map> &ResKernelModuleMap) { for (auto &F : M.functions()) { if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { if (OneKernelPerModule) { @@ -205,12 +206,12 @@ splitModule(Module &M, // Saves specified collection of llvm IR modules to files. // Saves file list if user specified corresponding filename. -static void saveResultModules(std::vector> &ResModules) { +static void +saveResultModules(std::vector> &ResModules) { std::string IRFilesList; for (size_t I = 0; I < ResModules.size(); ++I) { std::error_code EC; - std::string CurOutFileName = BaseOutputFilename + "_" + - std::to_string(I) + + std::string CurOutFileName = BaseOutputFilename + "_" + std::to_string(I) + ((OutputAssembly) ? ".ll" : ".bc"); raw_fd_ostream Out{CurOutFileName, EC, sys::fs::OF_None}; @@ -233,8 +234,7 @@ static void saveResultModules(std::vector> &ResModules) if (!OutputIRFilesList.empty()) { // Just pass input module to next tools if there was nothing to split. if (IRFilesList.empty()) - IRFilesList = - (Twine(InputFilename) + Twine("\n")).str(); + IRFilesList = (Twine(InputFilename) + Twine("\n")).str(); writeToFile(OutputIRFilesList, IRFilesList); } } @@ -313,8 +313,8 @@ int main(int argc, char **argv) { // Default usage model of that the tool is // calling it twice with the same input due clang driver limitations. // It should not bring much extra overhead because - // parseIRFile and collectKernelModuleMap functions are small (would be good to - // estimate) compared to splitModule and saveResultModules. + // parseIRFile and collectKernelModuleMap functions are small (would be good + // to estimate) compared to splitModule and saveResultModules. bool NoLists = OutputIRFilesList.empty() && OutputTxtFilesList.empty(); bool PerformSplit = !OutputIRFilesList.empty() || NoLists; bool CollectSymbols = !OutputTxtFilesList.empty() || NoLists;