#include "mlir/Target/LLVM/NVVM/Target.h"
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
#include "mlir/Target/LLVM/NVVM/Utils.h"
#include "mlir/Target/LLVMIR/Dialect/GPU/GPUToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Export.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
usingnamespacemlir;
usingnamespacemlir::NVVM;
#ifndef __DEFAULT_CUDATOOLKIT_PATH__
#define __DEFAULT_CUDATOOLKIT_PATH__ …
#endif
namespace {
class NVVMTargetAttrImpl
: public gpu::TargetAttrInterface::FallbackModel<NVVMTargetAttrImpl> { … };
}
void mlir::NVVM::registerNVVMTargetInterfaceExternalModels(
DialectRegistry ®istry) { … }
void mlir::NVVM::registerNVVMTargetInterfaceExternalModels(
MLIRContext &context) { … }
StringRef mlir::NVVM::getCUDAToolkitPath() { … }
SerializeGPUModuleBase::SerializeGPUModuleBase(
Operation &module, NVVMTargetAttr target,
const gpu::TargetOptions &targetOptions)
: … { … }
void SerializeGPUModuleBase::init() { … }
NVVMTargetAttr SerializeGPUModuleBase::getTarget() const { … }
StringRef SerializeGPUModuleBase::getToolkitPath() const { … }
ArrayRef<std::string> SerializeGPUModuleBase::getFileList() const { … }
LogicalResult SerializeGPUModuleBase::appendStandardLibs() { … }
std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
SerializeGPUModuleBase::loadBitcodeFiles(llvm::Module &module) { … }
namespace {
class NVPTXSerializer : public SerializeGPUModuleBase { … };
}
NVPTXSerializer::NVPTXSerializer(Operation &module, NVVMTargetAttr target,
const gpu::TargetOptions &targetOptions)
: … { … }
std::optional<NVPTXSerializer::TmpFile>
NVPTXSerializer::createTemp(StringRef name, StringRef suffix) { … }
gpu::GPUModuleOp NVPTXSerializer::getOperation() { … }
std::optional<std::string> NVPTXSerializer::findTool(StringRef tool) { … }
std::optional<SmallVector<char, 0>>
NVPTXSerializer::compileToBinary(const std::string &ptxCode) { … }
#if MLIR_ENABLE_NVPTXCOMPILER
#include "nvPTXCompiler.h"
#define RETURN_ON_NVPTXCOMPILER_ERROR …
std::optional<SmallVector<char, 0>>
NVPTXSerializer::compileToBinaryNVPTX(const std::string &ptxCode) {
Location loc = getOperation().getLoc();
nvPTXCompilerHandle compiler = nullptr;
nvPTXCompileResult status;
size_t logSize;
std::string optLevel = std::to_string(this->optLevel);
std::pair<llvm::BumpPtrAllocator, SmallVector<const char *>> cmdOpts =
targetOptions.tokenizeCmdOptions();
cmdOpts.second.append(
{"-arch", getTarget().getChip().data(), "--opt-level", optLevel.c_str()});
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerCreate(&compiler, ptxCode.size(), ptxCode.c_str()));
status = nvPTXCompilerCompile(compiler, cmdOpts.second.size(),
cmdOpts.second.data());
if (status != NVPTXCOMPILE_SUCCESS) {
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetErrorLogSize(compiler, &logSize));
if (logSize != 0) {
SmallVector<char> log(logSize + 1, 0);
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetErrorLog(compiler, log.data()));
emitError(loc) << "NVPTX compiler invocation failed, error log: "
<< log.data();
} else
emitError(loc) << "NVPTX compiler invocation failed with error code: "
<< status;
return std::nullopt;
}
size_t elfSize;
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetCompiledProgramSize(compiler, &elfSize));
SmallVector<char, 0> binary(elfSize, 0);
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetCompiledProgram(compiler, (void *)binary.data()));
#define DEBUG_TYPE …
LLVM_DEBUG({
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetInfoLogSize(compiler, &logSize));
if (logSize != 0) {
SmallVector<char> log(logSize + 1, 0);
RETURN_ON_NVPTXCOMPILER_ERROR(
nvPTXCompilerGetInfoLog(compiler, log.data()));
llvm::dbgs() << "NVPTX compiler invocation for module: "
<< getOperation().getNameAttr() << "\n";
llvm::dbgs() << "Arguments: ";
llvm::interleave(cmdOpts.second, llvm::dbgs(), " ");
llvm::dbgs() << "\nOutput\n" << log.data() << "\n";
llvm::dbgs().flush();
}
});
#undef DEBUG_TYPE
RETURN_ON_NVPTXCOMPILER_ERROR(nvPTXCompilerDestroy(&compiler));
return binary;
}
#endif
std::optional<SmallVector<char, 0>>
NVPTXSerializer::moduleToObject(llvm::Module &llvmModule) { … }
std::optional<SmallVector<char, 0>>
NVVMTargetAttrImpl::serializeToObject(Attribute attribute, Operation *module,
const gpu::TargetOptions &options) const { … }
Attribute
NVVMTargetAttrImpl::createObject(Attribute attribute, Operation *module,
const SmallVector<char, 0> &object,
const gpu::TargetOptions &options) const { … }