MLIR  20.0.0git
Target.cpp
Go to the documentation of this file.
1 //===- Target.cpp - MLIR LLVM ROCDL target compilation ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This files defines ROCDL target related functions including registration
10 // calls for the `#rocdl.target` compilation attribute.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 
21 
22 #include "llvm/IR/Constants.h"
23 #include "llvm/MC/MCAsmBackend.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCCodeEmitter.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCInstrInfo.h"
28 #include "llvm/MC/MCObjectFileInfo.h"
29 #include "llvm/MC/MCObjectWriter.h"
30 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSubtargetInfo.h"
34 #include "llvm/MC/TargetRegistry.h"
35 #include "llvm/Support/FileSystem.h"
36 #include "llvm/Support/FileUtilities.h"
37 #include "llvm/Support/Path.h"
38 #include "llvm/Support/Program.h"
39 #include "llvm/Support/SourceMgr.h"
40 #include "llvm/Support/TargetSelect.h"
41 #include "llvm/TargetParser/TargetParser.h"
42 
43 #include <cstdlib>
44 #include <optional>
45 
46 using namespace mlir;
47 using namespace mlir::ROCDL;
48 
49 #ifndef __DEFAULT_ROCM_PATH__
50 #define __DEFAULT_ROCM_PATH__ ""
51 #endif
52 
53 namespace {
54 // Implementation of the `TargetAttrInterface` model.
55 class ROCDLTargetAttrImpl
56  : public gpu::TargetAttrInterface::FallbackModel<ROCDLTargetAttrImpl> {
57 public:
58  std::optional<SmallVector<char, 0>>
59  serializeToObject(Attribute attribute, Operation *module,
60  const gpu::TargetOptions &options) const;
61 
62  Attribute createObject(Attribute attribute, Operation *module,
63  const SmallVector<char, 0> &object,
64  const gpu::TargetOptions &options) const;
65 };
66 } // namespace
67 
68 // Register the ROCDL dialect, the ROCDL translation and the target interface.
70  DialectRegistry &registry) {
71  registry.addExtension(+[](MLIRContext *ctx, ROCDL::ROCDLDialect *dialect) {
72  ROCDLTargetAttr::attachInterface<ROCDLTargetAttrImpl>(*ctx);
73  });
74 }
75 
77  MLIRContext &context) {
78  DialectRegistry registry;
80  context.appendDialectRegistry(registry);
81 }
82 
83 // Search for the ROCM path.
85  if (const char *var = std::getenv("ROCM_PATH"))
86  return var;
87  if (const char *var = std::getenv("ROCM_ROOT"))
88  return var;
89  if (const char *var = std::getenv("ROCM_HOME"))
90  return var;
91  return __DEFAULT_ROCM_PATH__;
92 }
93 
95  Operation &module, ROCDLTargetAttr target,
96  const gpu::TargetOptions &targetOptions)
97  : ModuleToObject(module, target.getTriple(), target.getChip(),
98  target.getFeatures(), target.getO()),
99  target(target), toolkitPath(targetOptions.getToolkitPath()),
100  fileList(targetOptions.getLinkFiles()) {
101 
102  // If `targetOptions` has an empty toolkitPath use `getROCMPath`
103  if (toolkitPath.empty())
105 
106  // Append the files in the target attribute.
107  if (ArrayAttr files = target.getLink())
108  for (Attribute attr : files.getValue())
109  if (auto file = dyn_cast<StringAttr>(attr))
110  fileList.push_back(file.str());
111 }
112 
114  static llvm::once_flag initializeBackendOnce;
115  llvm::call_once(initializeBackendOnce, []() {
116  // If the `AMDGPU` LLVM target was built, initialize it.
117 #if MLIR_ENABLE_ROCM_CONVERSIONS
118  LLVMInitializeAMDGPUTarget();
119  LLVMInitializeAMDGPUTargetInfo();
120  LLVMInitializeAMDGPUTargetMC();
121  LLVMInitializeAMDGPUAsmParser();
122  LLVMInitializeAMDGPUAsmPrinter();
123 #endif
124  });
125 }
126 
127 ROCDLTargetAttr SerializeGPUModuleBase::getTarget() const { return target; }
128 
130 
132  return fileList;
133 }
134 
136  if (libs == AMDGCNLibraries::None)
137  return success();
138  StringRef pathRef = getToolkitPath();
139 
140  // Get the path for the device libraries
141  SmallString<256> path;
142  path.insert(path.begin(), pathRef.begin(), pathRef.end());
143  llvm::sys::path::append(path, "amdgcn", "bitcode");
144  pathRef = StringRef(path.data(), path.size());
145 
146  // Fail if the path is invalid.
147  if (!llvm::sys::fs::is_directory(pathRef)) {
148  getOperation().emitError() << "ROCm amdgcn bitcode path: " << pathRef
149  << " does not exist or is not a directory";
150  return failure();
151  }
152 
153  // Helper function for adding a library.
154  auto addLib = [&](const Twine &lib) -> bool {
155  auto baseSize = path.size();
156  llvm::sys::path::append(path, lib);
157  StringRef pathRef(path.data(), path.size());
158  if (!llvm::sys::fs::is_regular_file(pathRef)) {
159  getOperation().emitRemark() << "bitcode library path: " << pathRef
160  << " does not exist or is not a file";
161  return true;
162  }
163  fileList.push_back(pathRef.str());
164  path.truncate(baseSize);
165  return false;
166  };
167 
168  // Add ROCm device libraries. Fail if any of the libraries is not found, ie.
169  // if any of the `addLib` failed.
170  if ((any(libs & AMDGCNLibraries::Ocml) && addLib("ocml.bc")) ||
171  (any(libs & AMDGCNLibraries::Ockl) && addLib("ockl.bc")) ||
172  (any(libs & AMDGCNLibraries::Hip) && addLib("hip.bc")) ||
173  (any(libs & AMDGCNLibraries::OpenCL) && addLib("opencl.bc")))
174  return failure();
175  return success();
176 }
177 
178 std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
180  // Return if there are no libs to load.
181  if (deviceLibs == AMDGCNLibraries::None && fileList.empty())
183  if (failed(appendStandardLibs(deviceLibs)))
184  return std::nullopt;
186  if (failed(loadBitcodeFilesFromList(module.getContext(), fileList, bcFiles,
187  true)))
188  return std::nullopt;
189  return std::move(bcFiles);
190 }
191 
192 LogicalResult SerializeGPUModuleBase::handleBitcodeFile(llvm::Module &module) {
193  // Some ROCM builds don't strip this like they should
194  if (auto *openclVersion = module.getNamedMetadata("opencl.ocl.version"))
195  module.eraseNamedMetadata(openclVersion);
196  // Stop spamming us with clang version numbers
197  if (auto *ident = module.getNamedMetadata("llvm.ident"))
198  module.eraseNamedMetadata(ident);
199  // Override the libModules datalayout and target triple with the compiler's
200  // data layout should there be a discrepency.
202  return success();
203 }
204 
206  // If all libraries are not set, traverse the module to determine which
207  // libraries are required.
209  for (llvm::Function &f : module.functions()) {
210  if (f.hasExternalLinkage() && f.hasName() && !f.hasExactDefinition()) {
211  StringRef funcName = f.getName();
212  if ("printf" == funcName)
215  if (funcName.starts_with("__ockl_"))
217  if (funcName.starts_with("__ocml_"))
219  if (funcName == "__atomic_work_item_fence")
221  }
222  }
223  }
224  addControlVariables(module, deviceLibs, target.hasWave64(), target.hasDaz(),
225  target.hasFiniteOnly(), target.hasUnsafeMath(),
226  target.hasFastMath(), target.hasCorrectSqrt(),
227  target.getAbi());
228 }
229 
231  llvm::Module &module, AMDGCNLibraries libs, bool wave64, bool daz,
232  bool finiteOnly, bool unsafeMath, bool fastMath, bool correctSqrt,
233  StringRef abiVer) {
234  // Helper function for adding control variables.
235  auto addControlVariable = [&module](StringRef name, uint32_t value,
236  uint32_t bitwidth) {
237  if (module.getNamedGlobal(name))
238  return;
239  llvm::IntegerType *type =
240  llvm::IntegerType::getIntNTy(module.getContext(), bitwidth);
241  llvm::GlobalVariable *controlVariable = new llvm::GlobalVariable(
242  module, /*isConstant=*/type, true,
243  llvm::GlobalValue::LinkageTypes::LinkOnceODRLinkage,
244  llvm::ConstantInt::get(type, value), name, /*before=*/nullptr,
245  /*threadLocalMode=*/llvm::GlobalValue::ThreadLocalMode::NotThreadLocal,
246  /*addressSpace=*/4);
247  controlVariable->setVisibility(
248  llvm::GlobalValue::VisibilityTypes::ProtectedVisibility);
249  controlVariable->setAlignment(llvm::MaybeAlign(bitwidth / 8));
250  controlVariable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Local);
251  };
252 
253  int abi = 500;
254  abiVer.getAsInteger(0, abi);
255  module.addModuleFlag(llvm::Module::Error, "amdhsa_code_object_version", abi);
256  // Return if no device libraries are required.
257  if (libs == AMDGCNLibraries::None)
258  return;
259  // Add ocml related control variables.
260  if (any(libs & AMDGCNLibraries::Ocml)) {
261  addControlVariable("__oclc_finite_only_opt", finiteOnly || fastMath, 8);
262  addControlVariable("__oclc_daz_opt", daz || fastMath, 8);
263  addControlVariable("__oclc_correctly_rounded_sqrt32",
264  correctSqrt && !fastMath, 8);
265  addControlVariable("__oclc_unsafe_math_opt", unsafeMath || fastMath, 8);
266  }
267  // Add ocml or ockl related control variables.
268  if (any(libs & (AMDGCNLibraries::Ocml | AMDGCNLibraries::Ockl))) {
269  addControlVariable("__oclc_wavefrontsize64", wave64, 8);
270  // Get the ISA version.
271  llvm::AMDGPU::IsaVersion isaVersion = llvm::AMDGPU::getIsaVersion(chip);
272  // Add the ISA control variable.
273  addControlVariable("__oclc_ISA_version",
274  isaVersion.Minor + 100 * isaVersion.Stepping +
275  1000 * isaVersion.Major,
276  32);
277  addControlVariable("__oclc_ABI_version", abi, 32);
278  }
279 }
280 
281 std::optional<SmallVector<char, 0>>
283  auto loc = getOperation().getLoc();
284 
285  StringRef targetTriple = this->triple;
286 
287  SmallVector<char, 0> result;
288  llvm::raw_svector_ostream os(result);
289 
290  llvm::Triple triple(llvm::Triple::normalize(targetTriple));
291  std::string error;
292  const llvm::Target *target =
293  llvm::TargetRegistry::lookupTarget(triple.normalize(), error);
294  if (!target) {
295  emitError(loc, Twine("failed to lookup target: ") + error);
296  return std::nullopt;
297  }
298 
299  llvm::SourceMgr srcMgr;
300  srcMgr.AddNewSourceBuffer(llvm::MemoryBuffer::getMemBuffer(isa), SMLoc());
301 
302  const llvm::MCTargetOptions mcOptions;
303  std::unique_ptr<llvm::MCRegisterInfo> mri(
304  target->createMCRegInfo(targetTriple));
305  std::unique_ptr<llvm::MCAsmInfo> mai(
306  target->createMCAsmInfo(*mri, targetTriple, mcOptions));
307  std::unique_ptr<llvm::MCSubtargetInfo> sti(
308  target->createMCSubtargetInfo(targetTriple, chip, features));
309 
310  llvm::MCContext ctx(triple, mai.get(), mri.get(), sti.get(), &srcMgr,
311  &mcOptions);
312  std::unique_ptr<llvm::MCObjectFileInfo> mofi(target->createMCObjectFileInfo(
313  ctx, /*PIC=*/false, /*LargeCodeModel=*/false));
314  ctx.setObjectFileInfo(mofi.get());
315 
316  SmallString<128> cwd;
317  if (!llvm::sys::fs::current_path(cwd))
318  ctx.setCompilationDir(cwd);
319 
320  std::unique_ptr<llvm::MCStreamer> mcStreamer;
321  std::unique_ptr<llvm::MCInstrInfo> mcii(target->createMCInstrInfo());
322 
323  llvm::MCCodeEmitter *ce = target->createMCCodeEmitter(*mcii, ctx);
324  llvm::MCAsmBackend *mab = target->createMCAsmBackend(*sti, *mri, mcOptions);
325  mcStreamer.reset(target->createMCObjectStreamer(
326  triple, ctx, std::unique_ptr<llvm::MCAsmBackend>(mab),
327  mab->createObjectWriter(os), std::unique_ptr<llvm::MCCodeEmitter>(ce),
328  *sti));
329 
330  std::unique_ptr<llvm::MCAsmParser> parser(
331  createMCAsmParser(srcMgr, ctx, *mcStreamer, *mai));
332  std::unique_ptr<llvm::MCTargetAsmParser> tap(
333  target->createMCAsmParser(*sti, *parser, *mcii, mcOptions));
334 
335  if (!tap) {
336  emitError(loc, "assembler initialization error");
337  return std::nullopt;
338  }
339 
340  parser->setTargetParser(*tap);
341  parser->Run(false);
342  return std::move(result);
343 }
344 
345 std::optional<SmallVector<char, 0>>
346 SerializeGPUModuleBase::compileToBinary(const std::string &serializedISA) {
347  // Assemble the ISA.
348  std::optional<SmallVector<char, 0>> isaBinary = assembleIsa(serializedISA);
349 
350  if (!isaBinary) {
351  getOperation().emitError() << "failed during ISA assembling";
352  return std::nullopt;
353  }
354 
355  // Save the ISA binary to a temp file.
356  int tempIsaBinaryFd = -1;
357  SmallString<128> tempIsaBinaryFilename;
358  if (llvm::sys::fs::createTemporaryFile("kernel%%", "o", tempIsaBinaryFd,
359  tempIsaBinaryFilename)) {
361  << "failed to create a temporary file for dumping the ISA binary";
362  return std::nullopt;
363  }
364  llvm::FileRemover cleanupIsaBinary(tempIsaBinaryFilename);
365  {
366  llvm::raw_fd_ostream tempIsaBinaryOs(tempIsaBinaryFd, true);
367  tempIsaBinaryOs << StringRef(isaBinary->data(), isaBinary->size());
368  tempIsaBinaryOs.flush();
369  }
370 
371  // Create a temp file for HSA code object.
372  SmallString<128> tempHsacoFilename;
373  if (llvm::sys::fs::createTemporaryFile("kernel", "hsaco",
374  tempHsacoFilename)) {
376  << "failed to create a temporary file for the HSA code object";
377  return std::nullopt;
378  }
379  llvm::FileRemover cleanupHsaco(tempHsacoFilename);
380 
382  llvm::sys::path::append(lldPath, "llvm", "bin", "ld.lld");
383  int lldResult = llvm::sys::ExecuteAndWait(
384  lldPath,
385  {"ld.lld", "-shared", tempIsaBinaryFilename, "-o", tempHsacoFilename});
386  if (lldResult != 0) {
387  getOperation().emitError() << "lld invocation failed";
388  return std::nullopt;
389  }
390 
391  // Load the HSA code object.
392  auto hsacoFile =
393  llvm::MemoryBuffer::getFile(tempHsacoFilename, /*IsText=*/false);
394  if (!hsacoFile) {
396  << "failed to read the HSA code object from the temp file";
397  return std::nullopt;
398  }
399 
400  StringRef buffer = (*hsacoFile)->getBuffer();
401 
402  return SmallVector<char, 0>(buffer.begin(), buffer.end());
403 }
404 
405 std::optional<SmallVector<char, 0>> SerializeGPUModuleBase::moduleToObjectImpl(
406  const gpu::TargetOptions &targetOptions, llvm::Module &llvmModule) {
407  // Return LLVM IR if the compilation target is offload.
408 #define DEBUG_TYPE "serialize-to-llvm"
409  LLVM_DEBUG({
410  llvm::dbgs() << "LLVM IR for module: "
411  << cast<gpu::GPUModuleOp>(getOperation()).getNameAttr() << "\n"
412  << llvmModule << "\n";
413  });
414 #undef DEBUG_TYPE
415  if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Offload)
416  return SerializeGPUModuleBase::moduleToObject(llvmModule);
417 
418  std::optional<llvm::TargetMachine *> targetMachine =
420  if (!targetMachine) {
421  getOperation().emitError() << "target Machine unavailable for triple "
422  << triple << ", can't compile with LLVM";
423  return std::nullopt;
424  }
425 
426  // Translate the Module to ISA.
427  std::optional<std::string> serializedISA =
428  translateToISA(llvmModule, **targetMachine);
429  if (!serializedISA) {
430  getOperation().emitError() << "failed translating the module to ISA";
431  return std::nullopt;
432  }
433 #define DEBUG_TYPE "serialize-to-isa"
434  LLVM_DEBUG({
435  llvm::dbgs() << "ISA for module: "
436  << cast<gpu::GPUModuleOp>(getOperation()).getNameAttr() << "\n"
437  << *serializedISA << "\n";
438  });
439 #undef DEBUG_TYPE
440  // Return ISA assembly code if the compilation target is assembly.
441  if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Assembly)
442  return SmallVector<char, 0>(serializedISA->begin(), serializedISA->end());
443 
444  // Compiling to binary requires a valid ROCm path, fail if it's not found.
445  if (getToolkitPath().empty()) {
446  getOperation().emitError() << "invalid ROCm path, please set a valid path";
447  return std::nullopt;
448  }
449 
450  // Compile to binary.
451  return compileToBinary(*serializedISA);
452 }
453 
454 #if MLIR_ENABLE_ROCM_CONVERSIONS
455 namespace {
456 class AMDGPUSerializer : public SerializeGPUModuleBase {
457 public:
458  AMDGPUSerializer(Operation &module, ROCDLTargetAttr target,
459  const gpu::TargetOptions &targetOptions);
460 
461  std::optional<SmallVector<char, 0>>
462  moduleToObject(llvm::Module &llvmModule) override;
463 
464 private:
465  // Target options.
466  gpu::TargetOptions targetOptions;
467 };
468 } // namespace
469 
470 AMDGPUSerializer::AMDGPUSerializer(Operation &module, ROCDLTargetAttr target,
471  const gpu::TargetOptions &targetOptions)
472  : SerializeGPUModuleBase(module, target, targetOptions),
473  targetOptions(targetOptions) {}
474 
475 std::optional<SmallVector<char, 0>>
476 AMDGPUSerializer::moduleToObject(llvm::Module &llvmModule) {
477  return moduleToObjectImpl(targetOptions, llvmModule);
478 }
479 #endif // MLIR_ENABLE_ROCM_CONVERSIONS
480 
481 std::optional<SmallVector<char, 0>> ROCDLTargetAttrImpl::serializeToObject(
482  Attribute attribute, Operation *module,
483  const gpu::TargetOptions &options) const {
484  assert(module && "The module must be non null.");
485  if (!module)
486  return std::nullopt;
487  if (!mlir::isa<gpu::GPUModuleOp>(module)) {
488  module->emitError("module must be a GPU module");
489  return std::nullopt;
490  }
491 #if MLIR_ENABLE_ROCM_CONVERSIONS
492  AMDGPUSerializer serializer(*module, cast<ROCDLTargetAttr>(attribute),
493  options);
494  serializer.init();
495  return serializer.run();
496 #else
497  module->emitError("the `AMDGPU` target was not built. Please enable it when "
498  "building LLVM");
499  return std::nullopt;
500 #endif // MLIR_ENABLE_ROCM_CONVERSIONS
501 }
502 
503 Attribute
504 ROCDLTargetAttrImpl::createObject(Attribute attribute, Operation *module,
505  const SmallVector<char, 0> &object,
506  const gpu::TargetOptions &options) const {
507  gpu::CompilationTarget format = options.getCompilationTarget();
508  // If format is `fatbin` transform it to binary as `fatbin` is not yet
509  // supported.
510  gpu::KernelTableAttr kernels;
511  if (format > gpu::CompilationTarget::Binary) {
512  format = gpu::CompilationTarget::Binary;
513  kernels = ROCDL::getKernelMetadata(module, object);
514  }
515  DictionaryAttr properties{};
516  Builder builder(attribute.getContext());
517  StringAttr objectStr =
518  builder.getStringAttr(StringRef(object.data(), object.size()));
519  return builder.getAttr<gpu::ObjectAttr>(attribute, format, objectStr,
520  properties, kernels);
521 }
#define __DEFAULT_ROCM_PATH__
Definition: Target.cpp:50
@ Error
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
Definition: Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:37
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
StringRef features
Target features.
static std::optional< std::string > translateToISA(llvm::Module &llvmModule, llvm::TargetMachine &targetMachine)
Utility function for translating to ISA, returns std::nullopt on failure.
virtual std::optional< SmallVector< char, 0 > > moduleToObject(llvm::Module &llvmModule)
Serializes the LLVM IR bitcode to an object file, by default it serializes to LLVM bitcode.
virtual void setDataLayoutAndTriple(llvm::Module &module)
Hook for computing the Datalayout.
StringRef triple
Target triple.
std::optional< llvm::TargetMachine * > getOrCreateTargetMachine()
Create the target machine based on the target triple and chip.
Operation & getOperation()
Returns the operation being serialized.
LogicalResult loadBitcodeFilesFromList(llvm::LLVMContext &context, ArrayRef< std::string > fileList, SmallVector< std::unique_ptr< llvm::Module >> &llvmModules, bool failureOnError=true)
Loads multiple bitcode files.
StringRef chip
Target chip.
Operation & module
Module to transform to a binary object.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:216
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:289
Base class for all ROCDL serializations from GPU modules into binary strings.
Definition: Utils.h:47
ROCDLTargetAttr getTarget() const
Returns the target attribute.
Definition: Target.cpp:127
ArrayRef< std::string > getFileList() const
Returns the bitcode files to be loaded.
Definition: Target.cpp:131
AMDGCNLibraries deviceLibs
AMD GCN libraries to use when linking, the default is using none.
Definition: Utils.h:113
ROCDLTargetAttr target
ROCDL target attribute.
Definition: Utils.h:104
SerializeGPUModuleBase(Operation &module, ROCDLTargetAttr target, const gpu::TargetOptions &targetOptions={})
Initializes the toolkitPath with the path in targetOptions or if empty with the path in getROCMPath.
Definition: Target.cpp:94
std::optional< SmallVector< char, 0 > > moduleToObjectImpl(const gpu::TargetOptions &targetOptions, llvm::Module &llvmModule)
Default implementation of ModuleToObject::moduleToObject.
Definition: Target.cpp:405
virtual std::optional< SmallVector< std::unique_ptr< llvm::Module > > > loadBitcodeFiles(llvm::Module &module) override
Loads the bitcode files in fileList.
Definition: Target.cpp:179
void addControlVariables(llvm::Module &module, AMDGCNLibraries libs, bool wave64, bool daz, bool finiteOnly, bool unsafeMath, bool fastMath, bool correctSqrt, StringRef abiVer)
Adds oclc control variables to the LLVM Module if needed.
Definition: Target.cpp:230
std::optional< SmallVector< char, 0 > > assembleIsa(StringRef isa)
Returns the assembled ISA.
Definition: Target.cpp:282
SmallVector< std::string > fileList
List of LLVM bitcode files to link to.
Definition: Utils.h:110
std::string toolkitPath
ROCM toolkit path.
Definition: Utils.h:107
static void init()
Initializes the LLVM AMDGPU target by safely calling LLVMInitializeAMDGPU* methods if available.
Definition: Target.cpp:113
StringRef getToolkitPath() const
Returns the ROCM toolkit path.
Definition: Target.cpp:129
LogicalResult appendStandardLibs(AMDGCNLibraries libs)
Appends standard ROCm device libraries to fileList.
Definition: Target.cpp:135
LogicalResult handleBitcodeFile(llvm::Module &module) override
Removes unnecessary metadata from the loaded bitcode files.
Definition: Target.cpp:192
virtual std::optional< SmallVector< char, 0 > > compileToBinary(const std::string &serializedISA)
Compiles assembly to a binary.
Definition: Target.cpp:346
void handleModulePreLink(llvm::Module &module) override
Determines required Device Libraries and adds oclc control variables to the LLVM Module if needed.
Definition: Target.cpp:205
This class serves as an opaque interface for passing options to the TargetAttrInterface methods.
CompilationTarget getCompilationTarget() const
Returns the compilation target.
void registerROCDLTargetInterfaceExternalModels(DialectRegistry &registry)
Registers the TargetAttrInterface for the #rocdl.target attribute in the given registry.
Definition: Target.cpp:69
AMDGCNLibraries
Helper enum for specifying the AMD GCN device libraries required for compilation.
Definition: Utils.h:34
gpu::KernelTableAttr getKernelMetadata(Operation *gpuModule, ArrayRef< char > elfData={})
Returns a #gpu.kernel_table containing kernel metadata for each of the kernels in gpuModule.
Definition: Utils.cpp:71
StringRef getROCMPath()
Searches & returns the path ROCM toolkit path, the search order is:
Definition: Target.cpp:84
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...