Skip to content

[SYCL] Add compile target to device image properties #14757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 32 additions & 13 deletions llvm/test/tools/sycl-post-link/multiple-filtered-outputs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,46 @@
; CHECK-ALL-EMPTY:

; PVC does not support sg8 (=1) or sg64 (=2)
; CHECK-PVC: _0.sym
; CHECK-PVC-NEXT: _3.sym
; CHECK-PVC-NEXT: _4.sym
; CHECK-PVC-NEXT: _5.sym
; CHECK-PVC: _intel_gpu_pvc_0.prop|{{.*}}_0.sym
; CHECK-PVC-NEXT: _intel_gpu_pvc_3.prop|{{.*}}_3.sym
; CHECK-PVC-NEXT: _intel_gpu_pvc_4.prop|{{.*}}_4.sym
; CHECK-PVC-NEXT: _intel_gpu_pvc_5.prop|{{.*}}_5.sym
; CHECK-PVC-EMPTY:

; RUN: FileCheck %s -input-file=%t_intel_gpu_pvc_0.prop -check-prefix=CHECK-PVC-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_pvc_3.prop -check-prefix=CHECK-PVC-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_pvc_4.prop -check-prefix=CHECK-PVC-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_pvc_5.prop -check-prefix=CHECK-PVC-PROP
; CHECK-PVC-PROP: compile_target=2|oBAAAAAAAAQauRXZs91ZwV3XwZ3Y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers about encoding this information into device image properties instead of re-using a dedicated field within device image data structure: as part of our transition to clang-linker-wrapper will try and unify our device image descriptors with those used in the upstream. There is an equivalent to our properties in there, but there are no dedicated field for device image target. Therefore, here we are using a mechanism that will be easier to transition later.


; TGLLP does not support fp64 (=0) or sg64 (=2)
; CHECK-TGLLP: _1.sym
; CHECK-TGLLP-NEXT: _3.sym
; CHECK-TGLLP-NEXT: _4.sym
; CHECK-TGLLP-NEXT: _5.sym
; CHECK-TGLLP: _intel_gpu_tgllp_1.prop|{{.*}}_1.sym
; CHECK-TGLLP-NEXT: _intel_gpu_tgllp_3.prop|{{.*}}_3.sym
; CHECK-TGLLP-NEXT: _intel_gpu_tgllp_4.prop|{{.*}}_4.sym
; CHECK-TGLLP-NEXT: _intel_gpu_tgllp_5.prop|{{.*}}_5.sym
; CHECK-TGLLP-EMPTY:

; RUN: FileCheck %s -input-file=%t_intel_gpu_tgllp_1.prop -check-prefix=CHECK-TGLLP-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_tgllp_3.prop -check-prefix=CHECK-TGLLP-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_tgllp_4.prop -check-prefix=CHECK-TGLLP-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_tgllp_5.prop -check-prefix=CHECK-TGLLP-PROP
; CHECK-TGLLP-PROP: compile_target=2|4BAAAAAAAAQauRXZs91ZwV3X0dGbsBH

; CFL does not support sg64 (=2)
; CHECK-CFL: _0.sym
; CHECK-CFL-NEXT: _1.sym
; CHECK-CFL-NEXT: _3.sym
; CHECK-CFL-NEXT: _4.sym
; CHECK-CFL-NEXT: _5.sym
; CHECK-CFL: _intel_gpu_cfl_0.prop|{{.*}}_0.sym
; CHECK-CFL-NEXT: _intel_gpu_cfl_1.prop|{{.*}}_1.sym
; CHECK-CFL-NEXT: _intel_gpu_cfl_3.prop|{{.*}}_3.sym
; CHECK-CFL-NEXT: _intel_gpu_cfl_4.prop|{{.*}}_4.sym
; CHECK-CFL-NEXT: _intel_gpu_cfl_5.prop|{{.*}}_5.sym
; CHECK-CFL-EMPTY:

; RUN: FileCheck %s -input-file=%t_intel_gpu_cfl_0.prop -check-prefix=CHECK-CFL-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_cfl_1.prop -check-prefix=CHECK-CFL-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_cfl_3.prop -check-prefix=CHECK-CFL-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_cfl_4.prop -check-prefix=CHECK-CFL-PROP
; RUN: FileCheck %s -input-file=%t_intel_gpu_cfl_5.prop -check-prefix=CHECK-CFL-PROP
; CHECK-CFL-PROP: compile_target=2|oBAAAAAAAAQauRXZs91ZwV3XjZGb

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
target triple = "spir64-unknown-unknown"

Expand Down
83 changes: 48 additions & 35 deletions llvm/tools/sycl-post-link/sycl-post-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ cl::opt<std::string> OutputDir{
cl::value_desc("dirname"), cl::cat(PostLinkCat)};

struct TargetFilenamePair {
std::optional<std::string> Target;
std::string Target;
std::string Filename;
};

Expand Down Expand Up @@ -305,13 +305,21 @@ std::string saveModuleIR(Module &M, int I, StringRef Suff) {

std::string saveModuleProperties(module_split::ModuleDesc &MD,
const GlobalBinImageProps &GlobProps, int I,
StringRef Suff) {
const auto &PropSet = computeModuleProperties(
MD.getModule(), MD.entries(), GlobProps, MD.Props.SpecConstsMet,
MD.isSpecConstantDefault());
StringRef Suff, StringRef Target = "") {
auto PropSet = computeModuleProperties(MD.getModule(), MD.entries(),
GlobProps, MD.Props.SpecConstsMet,
MD.isSpecConstantDefault());

std::string NewSuff = Suff.str();
if (!Target.empty()) {
PropSet.add(PropSetRegTy::SYCL_DEVICE_REQUIREMENTS, "compile_target",
Target);
NewSuff += "_";
NewSuff += Target;
}

std::error_code EC;
std::string SCFile = makeResultFileName(".prop", I, Suff);
std::string SCFile = makeResultFileName(".prop", I, NewSuff);
raw_fd_ostream SCOut(SCFile, EC);
checkError(EC, "error opening file '" + SCFile + "'");
PropSet.write(SCOut);
Expand Down Expand Up @@ -396,35 +404,46 @@ StringRef getModuleSuffix(const module_split::ModuleDesc &MD) {
return MD.isESIMD() ? "_esimd" : "";
}

bool isTargetCompatibleWithModule(const std::string &Target,
module_split::ModuleDesc &IrMD);

void addTableRow(util::SimpleTable &Table,
const IrPropSymFilenameTriple &RowData);

// @param OutTables List of tables (one for each target) to output results
// @param MD Module descriptor to save
// @param IRFilename filename of already available IR component. If not empty,
// IR component saving is skipped, and this file name is recorded as such in
// the result.
// @return a triple of files where IR, Property and Symbols components of the
// Module descriptor are written respectively.
IrPropSymFilenameTriple saveModule(module_split::ModuleDesc &MD, int I,
StringRef IRFilename = "") {
IrPropSymFilenameTriple Res;
void saveModule(std::vector<std::unique_ptr<util::SimpleTable>> &OutTables,
module_split::ModuleDesc &MD, int I, StringRef IRFilename) {
IrPropSymFilenameTriple BaseTriple;
StringRef Suffix = getModuleSuffix(MD);

if (!IRFilename.empty()) {
// don't save IR, just record the filename
Res.Ir = IRFilename.str();
BaseTriple.Ir = IRFilename.str();
} else {
MD.cleanup();
Res.Ir = saveModuleIR(MD.getModule(), I, Suffix);
BaseTriple.Ir = saveModuleIR(MD.getModule(), I, Suffix);
}
GlobalBinImageProps Props = {EmitKernelParamInfo, EmitProgramMetadata,
EmitExportedSymbols, EmitImportedSymbols,
DeviceGlobals};
if (DoPropGen)
Res.Prop = saveModuleProperties(MD, Props, I, Suffix);

if (DoSymGen) {
// save the names of the entry points - the symbol table
Res.Sym = saveModuleSymbolTable(MD, I, Suffix);
BaseTriple.Sym = saveModuleSymbolTable(MD, I, Suffix);
}

for (const auto &[Table, OutputFile] : zip_equal(OutTables, OutputFiles)) {
if (!isTargetCompatibleWithModule(OutputFile.Target, MD))
continue;
auto CopyTriple = BaseTriple;
if (DoPropGen) {
GlobalBinImageProps Props = {EmitKernelParamInfo, EmitProgramMetadata,
EmitExportedSymbols, EmitImportedSymbols,
DeviceGlobals};
CopyTriple.Prop =
saveModuleProperties(MD, Props, I, Suffix, OutputFile.Target);
}
addTableRow(*Table, CopyTriple);
}
return Res;
}

module_split::ModuleDesc link(module_split::ModuleDesc &&MD1,
Expand Down Expand Up @@ -680,25 +699,25 @@ handleESIMD(module_split::ModuleDesc &&MDesc, bool &Modified,
// information comes from the device config file (DeviceConfigFile.td).
// For example, the intel_gpu_tgllp target does not support fp64 - therefore,
// a module using fp64 would *not* be compatible with intel_gpu_tgllp.
bool isTargetCompatibleWithModule(const std::optional<std::string> &Target,
bool isTargetCompatibleWithModule(const std::string &Target,
module_split::ModuleDesc &IrMD) {
// When the user does not specify a target,
// (e.g. -o out.table compared to -o intel_gpu_pvc,out-pvc.table)
// Target will have no value and we will not want to perform any filtering, so
// Target will be empty and we will not want to perform any filtering, so
// we return true here.
if (!Target.has_value())
if (Target.empty())
return true;

// TODO: If a target not found in the device config file is passed,
// to sycl-post-link, then we should probably throw an error. However,
// since not all the information for all the targets is filled out
// right now, we return true, having the affect that unrecognized
// targets have no filtering applied to them.
if (!is_contained(DeviceConfigFile::TargetTable, *Target))
if (!is_contained(DeviceConfigFile::TargetTable, Target))
return true;

const DeviceConfigFile::TargetInfo &TargetInfo =
DeviceConfigFile::TargetTable[*Target];
DeviceConfigFile::TargetTable[Target];
const SYCLDeviceRequirements &ModuleReqs =
IrMD.getOrComputeDeviceRequirements();

Expand Down Expand Up @@ -856,21 +875,15 @@ processInputModule(std::unique_ptr<Module> M) {
"have been made\n";
}
for (module_split::ModuleDesc &IrMD : MMs) {
IrPropSymFilenameTriple T = saveModule(IrMD, ID, OutIRFileName);
for (const auto &[Table, OutputFile] : zip_equal(Tables, OutputFiles))
if (isTargetCompatibleWithModule(OutputFile.Target, IrMD))
addTableRow(*Table, T);
saveModule(Tables, IrMD, ID, OutIRFileName);
}

++ID;

if (!MMsWithDefaultSpecConsts.empty()) {
for (size_t i = 0; i != MMsWithDefaultSpecConsts.size(); ++i) {
module_split::ModuleDesc &IrMD = MMsWithDefaultSpecConsts[i];
IrPropSymFilenameTriple T = saveModule(IrMD, ID, OutIRFileName);
for (const auto &[Table, OutputFile] : zip_equal(Tables, OutputFiles))
if (isTargetCompatibleWithModule(OutputFile.Target, IrMD))
addTableRow(*Table, T);
saveModule(Tables, IrMD, ID, OutIRFileName);
}

++ID;
Expand Down
Loading