27#include "llvm/Support/InterleavedRange.h"
29#include "llvm/ADT/ScopeExit.h"
30#include "llvm/Config/Targets.h"
31#include "llvm/Support/DebugLog.h"
32#include "llvm/Support/FileSystem.h"
33#include "llvm/Support/FileUtilities.h"
34#include "llvm/Support/FormatVariadic.h"
35#include "llvm/Support/MemoryBuffer.h"
36#include "llvm/Support/Path.h"
37#include "llvm/Support/Process.h"
38#include "llvm/Support/Program.h"
39#include "llvm/Support/TargetSelect.h"
40#include "llvm/Support/Timer.h"
41#include "llvm/Support/raw_ostream.h"
50#ifndef __DEFAULT_CUDATOOLKIT_PATH__
51#define __DEFAULT_CUDATOOLKIT_PATH__ ""
59class NVVMTargetAttrImpl
60 :
public gpu::TargetAttrInterface::FallbackModel<NVVMTargetAttrImpl> {
62 std::optional<mlir::gpu::SerializedObject>
76 NVVMTargetAttr::attachInterface<NVVMTargetAttrImpl>(*ctx);
89 if (
const char *var = std::getenv(
"CUDA_ROOT"))
91 if (
const char *var = std::getenv(
"CUDA_HOME"))
93 if (
const char *var = std::getenv(
"CUDA_PATH"))
103 targetOptions.getInitialLlvmIRCallback(),
104 targetOptions.getLinkedLlvmIRCallback(),
105 targetOptions.getOptimizedLlvmIRCallback(),
106 targetOptions.getISACallback()),
123 static llvm::once_flag initializeBackendOnce;
124 llvm::call_once(initializeBackendOnce, []() {
126#if LLVM_HAS_NVPTX_TARGET
127 LLVMInitializeNVPTXTarget();
128 LLVMInitializeNVPTXTargetInfo();
129 LLVMInitializeNVPTXTargetMC();
130 LLVMInitializeNVPTXAsmPrinter();
145#if MLIR_NVVM_EMBED_LIBDEVICE
151 IntegerType::get(ctx, 8));
156 resourceManager.getBlobManager().lookup(
"_mlir_embedded_libdevice");
170 type, resourceManager.insert(
"_mlir_embedded_libdevice",
171 std::move(unmanagedBlob))));
174 if (!pathRef.empty()) {
176 path.insert(path.begin(), pathRef.begin(), pathRef.end());
177 pathRef = StringRef(path.data(), path.size());
178 if (!llvm::sys::fs::is_directory(pathRef)) {
180 <<
" does not exist or is not a directory.\n";
183 llvm::sys::path::append(path,
"nvvm",
"libdevice",
"libdevice.10.bc");
184 pathRef = StringRef(path.data(), path.size());
185 if (!llvm::sys::fs::is_regular_file(pathRef)) {
187 <<
" does not exist or is not a file.\n";
196std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
202 return std::move(bcFiles);
212 gpu::GPUModuleOp getOperation();
215 FailureOr<SmallVector<char, 0>> compileToBinary(StringRef ptxCode);
218 FailureOr<SmallVector<char, 0>> compileToBinaryNVPTX(StringRef ptxCode);
222 FailureOr<SmallVector<char, 0>>
223 moduleToObject(llvm::Module &llvmModule)
override;
228 std::optional<int64_t> getLLVMIRToISATimeInMs();
233 std::optional<int64_t> getISAToBinaryTimeInMs();
236 StringRef getISACompilerLog()
const;
239 using TmpFile = std::pair<llvm::SmallString<128>, llvm::FileRemover>;
242 std::optional<TmpFile> createTemp(StringRef name, StringRef suffix);
249 std::optional<std::string> findTool(StringRef tool);
255 std::optional<int64_t> llvmToISATimeInMs;
258 std::optional<int64_t> isaToBinaryTimeInMs;
261 std::string isaCompilerLog;
265NVPTXSerializer::NVPTXSerializer(
Operation &module, NVVMTargetAttr
target,
268 targetOptions(targetOptions), llvmToISATimeInMs(std::nullopt),
269 isaToBinaryTimeInMs(std::nullopt) {}
271std::optional<NVPTXSerializer::TmpFile>
272NVPTXSerializer::createTemp(StringRef name, StringRef suffix) {
273 llvm::SmallString<128> filename;
274 if (name.size() > 80)
275 name = name.substr(0, 80);
277 llvm::sys::fs::createTemporaryFile(name, suffix, filename);
279 getOperation().emitError() <<
"Couldn't create the temp file: `" << filename
280 <<
"`, error message: " << ec.message();
283 return TmpFile(filename, llvm::FileRemover(filename.c_str()));
286std::optional<int64_t> NVPTXSerializer::getLLVMIRToISATimeInMs() {
287 return llvmToISATimeInMs;
290std::optional<int64_t> NVPTXSerializer::getISAToBinaryTimeInMs() {
291 return isaToBinaryTimeInMs;
294StringRef NVPTXSerializer::getISACompilerLog()
const {
return isaCompilerLog; }
296gpu::GPUModuleOp NVPTXSerializer::getOperation() {
300std::optional<std::string> NVPTXSerializer::findTool(StringRef tool) {
303 StringRef pathRef = targetOptions.getToolkitPath();
304 SmallVector<char, 256> path;
305 if (!pathRef.empty()) {
306 path.insert(path.begin(), pathRef.begin(), pathRef.end());
307 llvm::sys::path::append(path,
"bin", tool);
308 if (llvm::sys::fs::can_execute(path))
309 return StringRef(path.data(), path.size()).str();
313 if (std::optional<std::string> toolPath =
314 llvm::sys::Process::FindInEnvPath(
"PATH", tool))
320 if (!pathRef.empty()) {
321 path.insert(path.begin(), pathRef.begin(), pathRef.end());
322 llvm::sys::path::append(path,
"bin", tool);
323 if (llvm::sys::fs::can_execute(path))
324 return StringRef(path.data(), path.size()).str();
326 getOperation().emitError()
327 <<
"Couldn't find the `" << tool
328 <<
"` binary. Please specify the toolkit "
329 "path, add the compiler to $PATH, or set one of the environment "
330 "variables in `NVVM::getCUDAToolkitPath()`.";
338 if (!
target.hasCmdOptions())
341 std::optional<mlir::NamedAttribute> cmdOptions =
target.getCmdOptions();
342 for (
Attribute attr : cast<ArrayAttr>(cmdOptions->getValue())) {
343 if (
auto strAttr = dyn_cast<StringAttr>(attr)) {
344 if constexpr (std::is_same_v<T, StringRef>) {
345 ptxasArgs.push_back(strAttr.getValue());
346 }
else if constexpr (std::is_same_v<T, const char *>) {
347 ptxasArgs.push_back(strAttr.getValue().data());
355FailureOr<SmallVector<char, 0>>
356NVPTXSerializer::compileToBinary(StringRef ptxCode) {
359 const bool createFatbin =
360 targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin;
363 std::optional<std::string> ptxasCompiler = findTool(
"ptxas");
366 std::optional<std::string> fatbinaryTool;
368 fatbinaryTool = findTool(
"fatbinary");
372 Location loc = getOperation().getLoc();
375 std::string basename =
376 llvm::formatv(
"mlir-{0}-{1}-{2}", getOperation().getNameAttr().getValue(),
377 getTarget().getTriple(), getTarget().getChip());
380 std::optional<TmpFile> ptxFile = createTemp(basename,
"ptx");
383 std::optional<TmpFile> logFile = createTemp(basename,
"log");
386 std::optional<TmpFile> binaryFile = createTemp(basename,
"bin");
391 std::string cubinFilename = (ptxFile->first +
".cubin").str();
392 cubinFile = TmpFile(cubinFilename, llvm::FileRemover(cubinFilename));
394 cubinFile.first = binaryFile->first;
400 llvm::raw_fd_ostream ptxStream(ptxFile->first, ec);
402 return emitError(loc) <<
"Couldn't open the file: `" << ptxFile->first
403 <<
"`, error message: " << ec.message();
405 ptxStream << ptxCode;
406 if (ptxStream.has_error())
407 return emitError(loc) <<
"An error occurred while writing the PTX to: `"
408 << ptxFile->first <<
"`.";
414 std::optional<StringRef> redirects[] = {
421 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
422 targetOptions.tokenizeCmdOptions();
425 std::string optLevel = std::to_string(this->optLevel);
426 SmallVector<StringRef, 12> ptxasArgs(
427 {StringRef(
"ptxas"), StringRef(
"-arch"), getTarget().getChip(),
428 StringRef(ptxFile->first), StringRef(
"-o"), StringRef(cubinFile.first),
429 "--opt-level", optLevel});
431 bool useFatbin32 =
false;
432 for (
const auto *cArg : cmdOpts.second) {
436 if (StringRef arg(cArg); arg !=
"-32")
437 ptxasArgs.push_back(arg);
446 StringRef chip = getTarget().getChip();
448 chip.consume_front(
"sm_"), chip.consume_front(
"compute_");
450 std::string cubinArg =
451 llvm::formatv(
"--image3=kind=elf,sm={0},file={1}", chip, cubinFile.first)
455 llvm::formatv(
"--image3=kind=ptx,sm={0},file={1}", chip, ptxFile->first)
457 SmallVector<StringRef, 6> fatbinArgs({StringRef(
"fatbinary"),
458 useFatbin32 ?
"-32" :
"-64", cubinArg,
459 ptxArg,
"--create", binaryFile->first});
462#define DEBUG_TYPE "serialize-to-binary"
463 LDBG() <<
"Tool invocation for module: " << getOperation().getNameAttr()
464 <<
"\nptxas executable:" << ptxasCompiler.value()
465 <<
"\nptxas args: " << llvm::interleaved(ptxasArgs,
" ");
467 LDBG() <<
"fatbin args: " << llvm::interleaved(fatbinArgs,
" ");
473 [&](StringRef toolName) -> FailureOr<SmallVector<char, 0>> {
474 if (message.empty()) {
475 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> toolStderr =
476 llvm::MemoryBuffer::getFile(logFile->first);
478 return emitError(loc) << toolName <<
" invocation failed. Log:\n"
479 << toolStderr->get()->getBuffer();
481 return emitError(loc) << toolName <<
" invocation failed.";
484 <<
" invocation failed, error message: " << message;
488 if (llvm::sys::ExecuteAndWait(ptxasCompiler.value(), ptxasArgs,
494 return emitLogError(
"`ptxas`");
496 if (
target.hasFlag(
"collect-compiler-diagnostics")) {
497 if (
auto logBuffer = llvm::MemoryBuffer::getFile(logFile->first))
498 isaCompilerLog = (*logBuffer)->getBuffer().str();
500#define DEBUG_TYPE "dump-sass"
502 std::optional<std::string> nvdisasm = findTool(
"nvdisasm");
503 SmallVector<StringRef> nvdisasmArgs(
504 {StringRef(
"nvdisasm"), StringRef(cubinFile.first)});
505 if (llvm::sys::ExecuteAndWait(nvdisasm.value(), nvdisasmArgs,
511 return emitLogError(
"`nvdisasm`");
512 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
513 llvm::MemoryBuffer::getFile(logFile->first);
514 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
515 LDBG() <<
"Output:\n" << (*logBuffer)->getBuffer();
516 llvm::dbgs().flush();
523 if (createFatbin && llvm::sys::ExecuteAndWait(*fatbinaryTool, fatbinArgs,
529 return emitLogError(
"`fatbinary`");
532#define DEBUG_TYPE "serialize-to-binary"
534 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> logBuffer =
535 llvm::MemoryBuffer::getFile(logFile->first);
536 if (logBuffer && !(*logBuffer)->getBuffer().empty()) {
537 LDBG() <<
"Output:\n" << (*logBuffer)->getBuffer();
538 llvm::dbgs().flush();
544 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> binaryBuffer =
545 llvm::MemoryBuffer::getFile(binaryFile->first);
547 return emitError(loc) <<
"Couldn't open the file: `" << binaryFile->first
548 <<
"`, error message: "
549 << binaryBuffer.getError().message();
551 StringRef fatbin = (*binaryBuffer)->getBuffer();
552 return SmallVector<char, 0>(fatbin.begin(), fatbin.end());
555#if MLIR_ENABLE_NVPTXCOMPILER
556#include "nvPTXCompiler.h"
558#define RETURN_ON_NVPTXCOMPILER_ERROR(expr) \
560 if (auto status = (expr)) { \
561 emitError(loc) << llvm::Twine(#expr).concat(" failed with error code ") \
569#define RETURN_ON_NVFATBIN_ERROR(expr) \
571 auto result = (expr); \
572 if (result != nvFatbinResult::NVFATBIN_SUCCESS) { \
573 emitError(loc) << llvm::Twine(#expr).concat(" failed with error: ") \
574 << nvFatbinGetErrorString(result); \
579FailureOr<SmallVector<char, 0>>
580NVPTXSerializer::compileToBinaryNVPTX(StringRef ptxCode) {
581 Location loc = getOperation().getLoc();
582 nvPTXCompilerHandle compiler =
nullptr;
583 nvPTXCompileResult status;
587 std::string optLevel = std::to_string(this->optLevel);
588 std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
589 targetOptions.tokenizeCmdOptions();
590 cmdOpts.second.append(
591 {
"-arch", getTarget().getChip().data(),
"--opt-level", optLevel.c_str()});
596 RETURN_ON_NVPTXCOMPILER_ERROR(
597 nvPTXCompilerCreate(&compiler, ptxCode.size(), ptxCode.str().c_str()));
600 status = nvPTXCompilerCompile(compiler, cmdOpts.second.size(),
601 cmdOpts.second.data());
604 if (status != NVPTXCOMPILE_SUCCESS) {
605 RETURN_ON_NVPTXCOMPILER_ERROR(
606 nvPTXCompilerGetErrorLogSize(compiler, &logSize));
608 SmallVector<char> log(logSize + 1, 0);
609 RETURN_ON_NVPTXCOMPILER_ERROR(
610 nvPTXCompilerGetErrorLog(compiler, log.data()));
612 <<
"NVPTX compiler invocation failed, error log: " << log.data();
615 <<
"NVPTX compiler invocation failed with error code: " << status;
621 RETURN_ON_NVPTXCOMPILER_ERROR(
622 nvPTXCompilerGetCompiledProgramSize(compiler, &elfSize));
623 SmallVector<char, 0> binary(elfSize, 0);
624 RETURN_ON_NVPTXCOMPILER_ERROR(
625 nvPTXCompilerGetCompiledProgram(compiler, (
void *)binary.data()));
628 auto fetchInfoLog = [&]() -> SmallVector<char> {
630 if (nvPTXCompilerGetInfoLogSize(compiler, &size) != NVPTXCOMPILE_SUCCESS ||
633 SmallVector<char> log(size + 1, 0);
634 if (nvPTXCompilerGetInfoLog(compiler, log.data()) != NVPTXCOMPILE_SUCCESS)
639 if (
target.hasFlag(
"collect-compiler-diagnostics")) {
640 if (
auto log = fetchInfoLog(); !log.empty())
641 isaCompilerLog = log.data();
645#define DEBUG_TYPE "serialize-to-binary"
647 if (
auto log = fetchInfoLog(); !log.empty())
648 LDBG() <<
"NVPTX compiler invocation for module: "
649 << getOperation().getNameAttr()
650 <<
"\nArguments: " << llvm::interleaved(cmdOpts.second,
" ")
655 RETURN_ON_NVPTXCOMPILER_ERROR(nvPTXCompilerDestroy(&compiler));
657 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Fatbin) {
658 bool useFatbin32 = llvm::any_of(cmdOpts.second, [](
const char *option) {
659 return llvm::StringRef(option) ==
"-32";
662 const char *cubinOpts[1] = {useFatbin32 ?
"-32" :
"-64"};
663 nvFatbinHandle handle;
665 auto chip = getTarget().getChip();
666 chip.consume_front(
"sm_");
668 RETURN_ON_NVFATBIN_ERROR(nvFatbinCreate(&handle, cubinOpts, 1));
669 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddCubin(
670 handle, binary.data(), binary.size(), chip.data(),
nullptr));
671 RETURN_ON_NVFATBIN_ERROR(nvFatbinAddPTX(
672 handle, ptxCode.data(), ptxCode.size(), chip.data(),
nullptr,
nullptr));
675 RETURN_ON_NVFATBIN_ERROR(nvFatbinSize(handle, &fatbinSize));
676 SmallVector<char, 0> fatbin(fatbinSize, 0);
677 RETURN_ON_NVFATBIN_ERROR(nvFatbinGet(handle, (
void *)fatbin.data()));
678 RETURN_ON_NVFATBIN_ERROR(nvFatbinDestroy(&handle));
686FailureOr<SmallVector<char, 0>>
687NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) {
688 llvm::Timer moduleToObjectTimer(
689 "moduleToObjectTimer",
690 "Timer for perf llvm-ir -> isa and isa -> binary.");
691 llvm::scope_exit
clear([&]() { moduleToObjectTimer.clear(); });
693#define DEBUG_TYPE "serialize-to-llvm"
695 LDBG() <<
"LLVM IR for module: " << getOperation().getNameAttr();
696 LDBG() << llvmModule;
699 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Offload)
702#if !LLVM_HAS_NVPTX_TARGET
703 return getOperation()->emitError(
704 "The `NVPTX` target was not built. Please enable it when building LLVM.");
708 FailureOr<llvm::TargetMachine *> targetMachine = getOrCreateTargetMachine();
709 if (
failed(targetMachine))
710 return getOperation().emitError()
711 <<
"Target Machine unavailable for triple " << triple
712 <<
", can't optimize with LLVM\n";
714 moduleToObjectTimer.startTimer();
715 FailureOr<SmallString<0>> serializedISA =
716 translateModuleToISA(llvmModule, **targetMachine,
717 [&]() {
return getOperation().emitError(); });
718 moduleToObjectTimer.stopTimer();
719 llvmToISATimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
720 moduleToObjectTimer.clear();
721 if (
failed(serializedISA))
722 return getOperation().emitError()
723 <<
"Failed translating the module to ISA.";
726 isaCallback(*serializedISA);
728#define DEBUG_TYPE "serialize-to-isa"
729 LDBG() <<
"PTX for module: " << getOperation().getNameAttr() <<
"\n"
734 if (targetOptions.getCompilationTarget() == gpu::CompilationTarget::Assembly)
735 return SmallVector<char, 0>(serializedISA->begin(), serializedISA->end());
737 FailureOr<SmallVector<char, 0>>
result;
738 moduleToObjectTimer.startTimer();
740#if MLIR_ENABLE_NVPTXCOMPILER
741 result = compileToBinaryNVPTX(*serializedISA);
743 result = compileToBinary(*serializedISA);
746 moduleToObjectTimer.stopTimer();
747 isaToBinaryTimeInMs = moduleToObjectTimer.getTotalTime().getWallTime() * 1000;
748 moduleToObjectTimer.clear();
752std::optional<mlir::gpu::SerializedObject>
753NVVMTargetAttrImpl::serializeToObject(Attribute attribute, Operation *module,
754 const gpu::TargetOptions &
options)
const {
756 assert(module &&
"The module must be non null.");
759 if (!mlir::isa<gpu::GPUModuleOp>(module)) {
760 module->emitError("Module must be a GPU module.");
763 NVPTXSerializer serializer(*module, cast<NVVMTargetAttr>(attribute),
options);
765 std::optional<SmallVector<char, 0>>
result = serializer.run();
769 SmallVector<NamedAttribute, 4> properties;
770 auto llvmToISATimeInMs = serializer.getLLVMIRToISATimeInMs();
771 if (llvmToISATimeInMs.has_value())
772 properties.push_back(builder.getNamedAttr(
773 "LLVMIRToISATimeInMs", builder.getI64IntegerAttr(*llvmToISATimeInMs)));
774 auto isaToBinaryTimeInMs = serializer.getISAToBinaryTimeInMs();
775 if (isaToBinaryTimeInMs.has_value())
776 properties.push_back(
777 builder.getNamedAttr(
"ISAToBinaryTimeInMs",
778 builder.getI64IntegerAttr(*isaToBinaryTimeInMs)));
779 StringRef isaCompilerLog = serializer.getISACompilerLog();
780 if (!isaCompilerLog.empty())
781 properties.push_back(builder.getNamedAttr(
782 "ISACompilerLog", builder.getStringAttr(isaCompilerLog)));
784 return gpu::SerializedObject{std::move(*
result),
785 builder.getDictionaryAttr(properties)};
789NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
790 const mlir::gpu::SerializedObject &
object,
791 const gpu::TargetOptions &
options)
const {
792 auto target = cast<NVVMTargetAttr>(attribute);
793 gpu::CompilationTarget format =
options.getCompilationTarget();
794 DictionaryAttr objectProps;
796 SmallVector<NamedAttribute> properties =
797 llvm::to_vector(
object.getMetadata().getValue());
798 if (format == gpu::CompilationTarget::Assembly)
799 properties.push_back(
800 builder.getNamedAttr(
"O", builder.getI32IntegerAttr(
target.getO())));
802 if (StringRef section =
options.getELFSection(); !section.empty())
804 builder.getStringAttr(section)));
806 if (!properties.empty())
807 objectProps = builder.getDictionaryAttr(properties);
809 return builder.getAttr<gpu::ObjectAttr>(
811 builder.getStringAttr(
812 StringRef(
object.getObject().data(),
object.getObject().size())),
813 objectProps,
nullptr);
static void setOptionalCommandlineArguments(NVVMTargetAttr target, SmallVectorImpl< T > &ptxasArgs)
Adds optional command-line arguments to existing arguments.
const unsigned _mlir_embedded_libdevice_size
#define __DEFAULT_CUDATOOLKIT_PATH__
const unsigned char _mlir_embedded_libdevice[]
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
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.
The class represents an individual entry of a blob.
LogicalResult loadBitcodeFilesFromList(llvm::LLVMContext &context, ArrayRef< Attribute > librariesToLink, SmallVector< std::unique_ptr< llvm::Module > > &llvmModules, bool failureOnError=true)
Loads multiple bitcode files.
virtual FailureOr< SmallVector< char, 0 > > moduleToObject(llvm::Module &llvmModule)
Serializes the LLVM IR bitcode to an object file, by default it serializes to LLVM bitcode.
Operation & getOperation()
Returns the operation being serialized.
ModuleToObject(Operation &module, StringRef triple, StringRef chip, StringRef features={}, int optLevel=3, function_ref< void(llvm::Module &)> initialLlvmIRCallback={}, function_ref< void(llvm::Module &)> linkedLlvmIRCallback={}, function_ref< void(llvm::Module &)> optimizedLlvmIRCallback={}, function_ref< void(StringRef)> isaCallback={})
Operation & module
Module to transform to a binary object.
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
Base class for all NVVM serializations from GPU modules into binary strings.
ArrayRef< Attribute > getLibrariesToLink() const
Returns the bitcode libraries to be linked into the gpu module after translation to LLVM IR.
SerializeGPUModuleBase(Operation &module, NVVMTargetAttr target, const gpu::TargetOptions &targetOptions={})
Initializes the toolkitPath with the path in targetOptions or if empty with the path in getCUDAToolki...
NVVMTargetAttr target
NVVM target attribute.
std::string toolkitPath
CUDA toolkit path.
SmallVector< Attribute > librariesToLink
List of LLVM bitcode to link into after translation to LLVM IR.
std::optional< SmallVector< std::unique_ptr< llvm::Module > > > loadBitcodeFiles(llvm::Module &module) override
Loads the bitcode files in librariesToLink.
LogicalResult appendStandardLibs()
Appends nvvm/libdevice.bc into librariesToLink.
static void init()
Initializes the LLVM NVPTX target by safely calling LLVMInitializeNVPTX* methods if available.
StringRef getToolkitPath() const
Returns the CUDA toolkit path.
NVVMTargetAttr getTarget() const
Returns the target attribute.
Operation is the basic unit of execution within MLIR.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
static AsmResourceBlob allocateInferAlign(ArrayRef< T > data, AsmResourceBlob::DeleterFn deleter={}, bool dataIsMutable=false)
This class represents a serialized object (GPU binary) with metadata (e.g.
This class serves as an opaque interface for passing options to the TargetAttrInterface methods.
void registerNVVMTargetInterfaceExternalModels(DialectRegistry ®istry)
Registers the TargetAttrInterface for the #nvvm.target attribute in the given registry.
StringRef getCUDAToolkitPath()
Searches & returns the path CUDA toolkit path, the search order is:
constexpr StringLiteral elfSectionName
Include the generated interface declarations.
DialectResourceBlobHandle< BuiltinDialect > DenseResourceElementsHandle
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
static ManagerInterface & getManagerInterface(MLIRContext *ctx)