Skip to content

Commit fa9e6b5

Browse files
committed
Embed required devicelib modules as device image
Signed-off-by: jinge90 <[email protected]>
1 parent 2e6387c commit fa9e6b5

File tree

7 files changed

+138
-14
lines changed

7 files changed

+138
-14
lines changed

llvm/include/llvm/SYCLLowerIR/ComputeModuleRuntimeInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "llvm/ADT/SetVector.h"
1414
#include "llvm/SYCLLowerIR/ModuleSplitter.h"
15+
#include "llvm/SYCLLowerIR/SYCLDeviceLibReqMask.h"
1516
#include "llvm/Support/PropertySetIO.h"
1617
#include <string>
1718
namespace llvm {

llvm/include/llvm/SYCLLowerIR/SYCLDeviceLibReqMask.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#pragma once
1818

1919
#include <cstdint>
20+
#include <string>
21+
#include <vector>
2022

2123
namespace llvm {
2224

@@ -39,5 +41,7 @@ enum class DeviceLibExt : std::uint32_t {
3941
};
4042

4143
uint32_t getSYCLDeviceLibReqMask(const Module &M);
42-
44+
void getSYCLDeviceLibReqNames(unsigned int ReqMask,
45+
std::vector<std::string> &ReqNames);
46+
unsigned int getSYCLDeviceLibMeta(std::string &DeviceLibFn);
4347
} // namespace llvm

llvm/include/llvm/Support/PropertySetIO.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ class PropertySetRegistry {
200200
static constexpr char SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[] =
201201
"SYCL/specialization constants default values";
202202
static constexpr char SYCL_DEVICELIB_REQ_MASK[] = "SYCL/devicelib req mask";
203+
static constexpr char SYCL_DEVICELIB_METADATA[] = "SYCL/devicelib metadata";
203204
static constexpr char SYCL_KERNEL_PARAM_OPT_INFO[] = "SYCL/kernel param opt";
204205
static constexpr char SYCL_PROGRAM_METADATA[] = "SYCL/program metadata";
205206
static constexpr char SYCL_MISC_PROP[] = "SYCL/misc properties";

llvm/lib/SYCLLowerIR/ComputeModuleRuntimeInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ PropSetRegTy computeModuleProperties(const Module &M,
160160
std::map<StringRef, uint32_t> RMEntry = {{"DeviceLibReqMask", MRMask}};
161161
PropSet.add(PropSetRegTy::SYCL_DEVICELIB_REQ_MASK, RMEntry);
162162
}
163+
163164
{
164165
PropSet.add(PropSetRegTy::SYCL_DEVICE_REQUIREMENTS,
165166
computeDeviceRequirements(M, EntryPoints).asMap());

llvm/lib/SYCLLowerIR/SYCLDeviceLibReqMask.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,28 @@ uint32_t getDeviceLibBits(const std::string &FuncName) {
757757

758758
} // namespace
759759

760+
static std::unordered_map<DeviceLibExt, std::vector<const char *>>
761+
SYCLDeviceLibFn = {
762+
{DeviceLibExt::cl_intel_devicelib_assert,
763+
{"libsycl-fallback-cassert.bc"}},
764+
{DeviceLibExt::cl_intel_devicelib_math, {"libsycl-fallback-cmath.bc"}},
765+
{DeviceLibExt::cl_intel_devicelib_math_fp64,
766+
{"libsycl-fallback-cmath-fp64.bc"}},
767+
{DeviceLibExt::cl_intel_devicelib_complex,
768+
{"libsycl-fallback-complex.bc"}},
769+
{DeviceLibExt::cl_intel_devicelib_complex_fp64,
770+
{"libsycl-fallback-complex-fp64.bc"}},
771+
{DeviceLibExt::cl_intel_devicelib_cstring,
772+
{"libsycl-fallback-cstring.bc"}},
773+
{DeviceLibExt::cl_intel_devicelib_imf, {"libsycl-fallback-imf.bc"}},
774+
{DeviceLibExt::cl_intel_devicelib_imf_fp64,
775+
{"libsycl-fallback-imf-fp64.bc"}},
776+
{DeviceLibExt::cl_intel_devicelib_imf_bf16,
777+
{"libsycl-fallback-imf-bf16.bc"}},
778+
{DeviceLibExt::cl_intel_devicelib_bfloat16,
779+
{"libsycl-fallback-bfloat16.bc", "libsycl-native-bfloat16.bc"}},
780+
};
781+
760782
// For each device image module, we go through all functions which meets
761783
// 1. The function name has prefix "__devicelib_"
762784
// 2. The function is declaration which means it doesn't have function body
@@ -775,3 +797,55 @@ uint32_t llvm::getSYCLDeviceLibReqMask(const Module &M) {
775797
}
776798
return ReqMask;
777799
}
800+
801+
void llvm::getSYCLDeviceLibReqNames(unsigned int ReqMask,
802+
std::vector<std::string> &ReqNames) {
803+
DeviceLibExt DeviceLibExts[] = {DeviceLibExt::cl_intel_devicelib_assert,
804+
DeviceLibExt::cl_intel_devicelib_math,
805+
DeviceLibExt::cl_intel_devicelib_math_fp64,
806+
DeviceLibExt::cl_intel_devicelib_complex,
807+
DeviceLibExt::cl_intel_devicelib_complex_fp64,
808+
DeviceLibExt::cl_intel_devicelib_cstring,
809+
DeviceLibExt::cl_intel_devicelib_imf,
810+
DeviceLibExt::cl_intel_devicelib_imf_fp64,
811+
DeviceLibExt::cl_intel_devicelib_imf_bf16,
812+
DeviceLibExt::cl_intel_devicelib_bfloat16};
813+
814+
unsigned int Temp;
815+
for (auto Ext : DeviceLibExts) {
816+
Temp =
817+
0x1 << (static_cast<size_t>(Ext) -
818+
static_cast<size_t>(DeviceLibExt::cl_intel_devicelib_assert));
819+
if (Temp & ReqMask) {
820+
for (auto Fn : SYCLDeviceLibFn[Ext])
821+
ReqNames.push_back(std::string(Fn));
822+
}
823+
}
824+
}
825+
826+
unsigned int llvm::getSYCLDeviceLibMeta(std::string &DeviceLibFn) {
827+
DeviceLibExt DeviceLibExts[] = {DeviceLibExt::cl_intel_devicelib_assert,
828+
DeviceLibExt::cl_intel_devicelib_math,
829+
DeviceLibExt::cl_intel_devicelib_math_fp64,
830+
DeviceLibExt::cl_intel_devicelib_complex,
831+
DeviceLibExt::cl_intel_devicelib_complex_fp64,
832+
DeviceLibExt::cl_intel_devicelib_cstring,
833+
DeviceLibExt::cl_intel_devicelib_imf,
834+
DeviceLibExt::cl_intel_devicelib_imf_fp64,
835+
DeviceLibExt::cl_intel_devicelib_imf_bf16,
836+
DeviceLibExt::cl_intel_devicelib_bfloat16};
837+
838+
unsigned int DeviceLibMeta = 0;
839+
for (auto Ext : DeviceLibExts) {
840+
for (auto Fn : SYCLDeviceLibFn[Ext]) {
841+
if (DeviceLibFn == Fn) {
842+
DeviceLibMeta = static_cast<unsigned int>(Ext);
843+
if (DeviceLibFn == "libsycl-native-bfloat16.bc")
844+
DeviceLibMeta |= 0x80000000ULL;
845+
break;
846+
}
847+
}
848+
}
849+
850+
return DeviceLibMeta;
851+
}

llvm/lib/Support/PropertySetIO.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ void PropertyValue::copy(const PropertyValue &P) {
196196

197197
constexpr char PropertySetRegistry::SYCL_SPECIALIZATION_CONSTANTS[];
198198
constexpr char PropertySetRegistry::SYCL_DEVICELIB_REQ_MASK[];
199+
constexpr char PropertySetRegistry::SYCL_DEVICELIB_METADATA[];
199200
constexpr char PropertySetRegistry::SYCL_SPEC_CONSTANTS_DEFAULT_VALUES[];
200201
constexpr char PropertySetRegistry::SYCL_KERNEL_PARAM_OPT_INFO[];
201202
constexpr char PropertySetRegistry::SYCL_PROGRAM_METADATA[];

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

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// - module splitter to split a big input module into smaller ones
1313
// - specialization constant intrinsic transformation
1414
//===----------------------------------------------------------------------===//
15-
1615
#include "llvm/ADT/SmallSet.h"
1716
#include "llvm/ADT/StringRef.h"
1817
#include "llvm/Analysis/AssumptionCache.h"
@@ -311,9 +310,20 @@ std::string saveModuleIR(Module &M, int I, StringRef Suff) {
311310

312311
std::string saveModuleProperties(module_split::ModuleDesc &MD,
313312
const GlobalBinImageProps &GlobProps, int I,
314-
StringRef Suff, StringRef Target = "") {
315-
auto PropSet =
316-
computeModuleProperties(MD.getModule(), MD.entries(), GlobProps);
313+
StringRef Suff, StringRef Target = "",
314+
bool IsDeviceLib = false) {
315+
PropSetRegTy PropSet;
316+
317+
// For fallback devicelib module, no kernel included and no specialization
318+
// constant used, skip regular Prop emit.
319+
if (!IsDeviceLib)
320+
PropSet = computeModuleProperties(MD.getModule(), MD.entries(), GlobProps);
321+
else {
322+
auto SYCLDeviceLibMeta = getSYCLDeviceLibMeta(MD.Name);
323+
std::map<StringRef, unsigned int> RMEntry = {
324+
{"DeviceLibMetaData", SYCLDeviceLibMeta}};
325+
PropSet.add(PropSetRegTy::SYCL_DEVICELIB_METADATA, RMEntry);
326+
}
317327

318328
std::string NewSuff = Suff.str();
319329
if (!Target.empty()) {
@@ -421,17 +431,24 @@ void addTableRow(util::SimpleTable &Table,
421431
// IR component saving is skipped, and this file name is recorded as such in
422432
// the result.
423433
void saveModule(std::vector<std::unique_ptr<util::SimpleTable>> &OutTables,
424-
module_split::ModuleDesc &MD, int I, StringRef IRFilename) {
434+
module_split::ModuleDesc &MD, int I, StringRef IRFilename,
435+
bool IsDeviceLib = false) {
425436
IrPropSymFilenameTriple BaseTriple;
426437
StringRef Suffix = getModuleSuffix(MD);
427438
MD.saveSplitInformationAsMetadata();
428-
if (!IRFilename.empty()) {
429-
// don't save IR, just record the filename
430-
BaseTriple.Ir = IRFilename.str();
439+
if (!IsDeviceLib) {
440+
if (!IRFilename.empty()) {
441+
// don't save IR, just record the filename
442+
BaseTriple.Ir = IRFilename.str();
443+
} else {
444+
MD.cleanup();
445+
BaseTriple.Ir = saveModuleIR(MD.getModule(), I, Suffix);
446+
}
431447
} else {
432-
MD.cleanup();
448+
// For DeviceLib Modules, don't need to do clean up.
433449
BaseTriple.Ir = saveModuleIR(MD.getModule(), I, Suffix);
434450
}
451+
435452
if (DoSymGen) {
436453
// save the names of the entry points - the symbol table
437454
BaseTriple.Sym = saveModuleSymbolTable(MD, I, Suffix);
@@ -445,13 +462,24 @@ void saveModule(std::vector<std::unique_ptr<util::SimpleTable>> &OutTables,
445462
GlobalBinImageProps Props = {EmitKernelParamInfo, EmitProgramMetadata,
446463
EmitExportedSymbols, EmitImportedSymbols,
447464
DeviceGlobals};
448-
CopyTriple.Prop =
449-
saveModuleProperties(MD, Props, I, Suffix, OutputFile.Target);
465+
CopyTriple.Prop = saveModuleProperties(MD, Props, I, Suffix,
466+
OutputFile.Target, IsDeviceLib);
450467
}
451468
addTableRow(*Table, CopyTriple);
452469
}
453470
}
454471

472+
void saveDeviceLibModule(
473+
std::vector<std::unique_ptr<util::SimpleTable>> &OutTables,
474+
const std::string &IRFile, int I, LLVMContext &Context) {
475+
SMDiagnostic Err;
476+
StringRef DeviceLibLoc = DeviceLibDir;
477+
std::string IRPath = DeviceLibLoc.str() + "/" + IRFile;
478+
std::unique_ptr<Module> IRModule = parseIRFile(IRPath, Err, Context);
479+
llvm::module_split::ModuleDesc LibIRMD(std::move(IRModule), IRFile);
480+
saveModule(OutTables, LibIRMD, I, IRFile, true);
481+
}
482+
455483
module_split::ModuleDesc link(module_split::ModuleDesc &&MD1,
456484
module_split::ModuleDesc &&MD2) {
457485
std::vector<std::string> Names;
@@ -747,7 +775,7 @@ bool isTargetCompatibleWithModule(const std::string &Target,
747775
}
748776

749777
std::vector<std::unique_ptr<util::SimpleTable>>
750-
processInputModule(std::unique_ptr<Module> M) {
778+
processInputModule(std::unique_ptr<Module> M, LLVMContext &Context) {
751779
// Construct the resulting table which will accumulate all the outputs.
752780
SmallVector<StringRef, MAX_COLUMNS_IN_FILE_TABLE> ColumnTitles{
753781
StringRef(COL_CODE)};
@@ -776,6 +804,9 @@ processInputModule(std::unique_ptr<Module> M) {
776804
// if none were made.
777805
bool Modified = false;
778806

807+
// Keeps track of required device libraries by all device images.
808+
unsigned int DeviceLibReqMask = 0;
809+
779810
// Propagate ESIMD attribute to wrapper functions to prevent
780811
// spurious splits and kernel link errors.
781812
Modified |= runModulePass<SYCLFixupESIMDKernelWrapperMDPass>(*M);
@@ -887,6 +918,7 @@ processInputModule(std::unique_ptr<Module> M) {
887918
"have been made\n";
888919
}
889920
for (module_split::ModuleDesc &IrMD : MMs) {
921+
DeviceLibReqMask |= getSYCLDeviceLibReqMask(IrMD.getModule());
890922
saveModule(Tables, IrMD, ID, OutIRFileName);
891923
}
892924

@@ -895,12 +927,22 @@ processInputModule(std::unique_ptr<Module> M) {
895927
if (!MMsWithDefaultSpecConsts.empty()) {
896928
for (size_t i = 0; i != MMsWithDefaultSpecConsts.size(); ++i) {
897929
module_split::ModuleDesc &IrMD = MMsWithDefaultSpecConsts[i];
930+
DeviceLibReqMask |= getSYCLDeviceLibReqMask(IrMD.getModule());
898931
saveModule(Tables, IrMD, ID, OutIRFileName);
899932
}
900933

901934
++ID;
902935
}
903936
}
937+
938+
if ((DeviceLibReqMask > 0) && (DeviceLibDir.getNumOccurrences() > 0)) {
939+
string_vector DeviceLibReqNames;
940+
getSYCLDeviceLibReqNames(DeviceLibReqMask, DeviceLibReqNames);
941+
for (auto Fn : DeviceLibReqNames) {
942+
saveDeviceLibModule(Tables, Fn, ID, Context);
943+
++ID;
944+
}
945+
}
904946
return Tables;
905947
}
906948

@@ -1044,7 +1086,7 @@ int main(int argc, char **argv) {
10441086
}
10451087

10461088
std::vector<std::unique_ptr<util::SimpleTable>> Tables =
1047-
processInputModule(std::move(M));
1089+
processInputModule(std::move(M), Context);
10481090

10491091
// Input module was processed and a single output file was requested.
10501092
if (IROutputOnly)

0 commit comments

Comments
 (0)