namespace LLVM {
+namespace detail {
+class DebugTranslation;
+} // end namespace detail
+
class LLVMFuncOp;
-// Implementation class for module translation. Holds a reference to the module
-// being translated, and the mappings between the original and the translated
-// functions, basic blocks and values. It is practically easier to hold these
-// mappings in one class since the conversion of control flow operations
-// needs to look up block and function mappings.
+/// Implementation class for module translation. Holds a reference to the module
+/// being translated, and the mappings between the original and the translated
+/// functions, basic blocks and values. It is practically easier to hold these
+/// mappings in one class since the conversion of control flow operations
+/// needs to look up block and function mappings.
class ModuleTranslation {
public:
template <typename T = ModuleTranslation>
if (!llvmModule)
return nullptr;
- T translator(m);
- translator.llvmModule = std::move(llvmModule);
+ T translator(m, std::move(llvmModule));
translator.convertGlobals();
if (failed(translator.convertFunctions()))
return nullptr;
static Block &getModuleBody(Operation *m) { return m->getRegion(0).front(); }
protected:
- // Translate the given MLIR module expressed in MLIR LLVM IR dialect into an
- // LLVM IR module. The MLIR LLVM IR dialect holds a pointer to an
- // LLVMContext, the LLVM IR module will be created in that context.
- explicit ModuleTranslation(Operation *module) : mlirModule(module) {
- assert(satisfiesLLVMModule(mlirModule) &&
- "mlirModule should honor LLVM's module semantics.");
- }
- virtual ~ModuleTranslation() {}
+ /// Translate the given MLIR module expressed in MLIR LLVM IR dialect into an
+ /// LLVM IR module. The MLIR LLVM IR dialect holds a pointer to an
+ /// LLVMContext, the LLVM IR module will be created in that context.
+ ModuleTranslation(Operation *module,
+ std::unique_ptr<llvm::Module> llvmModule);
+ virtual ~ModuleTranslation();
virtual LogicalResult convertOperation(Operation &op,
llvm::IRBuilder<> &builder);
llvm::Constant *getLLVMConstant(llvm::Type *llvmType, Attribute attr,
Location loc);
- // Original and translated module.
+ /// Original and translated module.
Operation *mlirModule;
std::unique_ptr<llvm::Module> llvmModule;
- // Mappings between llvm.mlir.global definitions and corresponding globals.
+ /// A converter for translating debug information.
+ std::unique_ptr<detail::DebugTranslation> debugTranslation;
+
+ /// Mappings between llvm.mlir.global definitions and corresponding globals.
DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
protected:
- // Mappings between original and translated values, used for lookups.
+ /// Mappings between original and translated values, used for lookups.
llvm::StringMap<llvm::Function *> functionMapping;
DenseMap<Value, llvm::Value *> valueMapping;
DenseMap<Block *, llvm::BasicBlock *> blockMapping;
std::unique_ptr<OpPassBase<FuncOp>> createMemRefDataFlowOptPass();
/// Creates a pass to strip debug information from a function.
-std::unique_ptr<OpPassBase<FuncOp>> createStripDebugInfoPass();
+std::unique_ptr<Pass> createStripDebugInfoPass();
/// Creates a pass which tests loop fusion utilities.
std::unique_ptr<OpPassBase<FuncOp>> createTestLoopFusionPass();
add_llvm_library(MLIRTargetLLVMIRModuleTranslation
+ LLVMIR/DebugTranslation.cpp
LLVMIR/ModuleTranslation.cpp
ADDITIONAL_HEADER_DIRS
namespace {
class ModuleTranslation : public LLVM::ModuleTranslation {
-
public:
- explicit ModuleTranslation(Operation *module)
- : LLVM::ModuleTranslation(module) {}
- ~ModuleTranslation() override {}
+ using LLVM::ModuleTranslation::ModuleTranslation;
protected:
LogicalResult convertOperation(Operation &opInst,
} // namespace
std::unique_ptr<llvm::Module> mlir::translateModuleToNVVMIR(Operation *m) {
- ModuleTranslation translation(m);
auto llvmModule =
LLVM::ModuleTranslation::translateModule<ModuleTranslation>(m);
if (!llvmModule)
namespace {
class ModuleTranslation : public LLVM::ModuleTranslation {
-
public:
- explicit ModuleTranslation(Operation *module)
- : LLVM::ModuleTranslation(module) {}
- ~ModuleTranslation() override {}
+ using LLVM::ModuleTranslation::ModuleTranslation;
protected:
LogicalResult convertOperation(Operation &opInst,
} // namespace
std::unique_ptr<llvm::Module> mlir::translateModuleToROCDLIR(Operation *m) {
- ModuleTranslation translation(m);
-
// lower MLIR (with RODL Dialect) to LLVM IR (with ROCDL intrinsics)
auto llvmModule =
LLVM::ModuleTranslation::translateModule<ModuleTranslation>(m);
--- /dev/null
+//===- DebugTranslation.cpp - MLIR to LLVM Debug conversion ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugTranslation.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace mlir;
+using namespace mlir::LLVM;
+using namespace mlir::LLVM::detail;
+
+/// A utility walker that interrupts if the operation has valid debug
+/// information.
+static WalkResult interruptIfValidLocation(Operation *op) {
+ return op->getLoc().isa<UnknownLoc>() ? WalkResult::advance()
+ : WalkResult::interrupt();
+}
+
+DebugTranslation::DebugTranslation(Operation *module, llvm::Module &llvmModule)
+ : builder(llvmModule), llvmCtx(llvmModule.getContext()),
+ compileUnit(nullptr) {
+
+ // If the module has no location information, there is nothing to do.
+ if (!module->walk(interruptIfValidLocation).wasInterrupted())
+ return;
+
+ // TODO(riverriddle) Several parts of this are incorrect. Different source
+ // languages may interpret different parts of the debug information
+ // differently. Frontends will also want to pipe in various information, like
+ // flags. This is fine for now as we only emit line-table information and not
+ // types or variables. This should disappear as the debug information story
+ // evolves; i.e. when we have proper attributes for LLVM debug metadata.
+ compileUnit = builder.createCompileUnit(
+ llvm::dwarf::DW_LANG_C,
+ builder.createFile(llvmModule.getModuleIdentifier(), "/"),
+ /*Producer=*/"mlir", /*isOptimized=*/true, /*Flags=*/"", /*RV=*/0);
+
+ // Mark this module as having debug information.
+ StringRef debugVersionKey = "Debug Info Version";
+ if (!llvmModule.getModuleFlag(debugVersionKey))
+ llvmModule.addModuleFlag(llvm::Module::Warning, debugVersionKey,
+ llvm::DEBUG_METADATA_VERSION);
+}
+
+/// Finalize the translation of debug information.
+void DebugTranslation::finalize() { builder.finalize(); }
+
+/// Attempt to extract a filename for the given loc.
+static FileLineColLoc extractFileLoc(Location loc) {
+ if (auto fileLoc = loc.dyn_cast<FileLineColLoc>())
+ return fileLoc;
+ if (auto nameLoc = loc.dyn_cast<NameLoc>())
+ return extractFileLoc(nameLoc.getChildLoc());
+ if (auto opaqueLoc = loc.dyn_cast<OpaqueLoc>())
+ return extractFileLoc(opaqueLoc.getFallbackLocation());
+ return FileLineColLoc();
+}
+
+/// Translate the debug information for the given function.
+void DebugTranslation::translate(LLVMFuncOp func, llvm::Function &llvmFunc) {
+ // If the function doesn't have location information, there is nothing to
+ // translate.
+ if (!compileUnit || !func.walk(interruptIfValidLocation).wasInterrupted())
+ return;
+
+ FileLineColLoc fileLoc = extractFileLoc(func.getLoc());
+ auto *file = translateFile(fileLoc ? fileLoc.getFilename() : "<unknown>");
+ unsigned line = fileLoc ? fileLoc.getLine() : 0;
+
+ // TODO(riverriddle) This is the bare essentials for now. We will likely end
+ // up with wrapper metadata around LLVMs metadata in the future, so this
+ // doesn't need to be smart until then.
+ llvm::DISubroutineType *type =
+ builder.createSubroutineType(builder.getOrCreateTypeArray(llvm::None));
+ llvm::DISubprogram::DISPFlags spFlags = llvm::DISubprogram::SPFlagDefinition |
+ llvm::DISubprogram::SPFlagOptimized;
+ llvm::DISubprogram *program =
+ builder.createFunction(compileUnit, func.getName(), func.getName(), file,
+ line, type, line, llvm::DINode::FlagZero, spFlags);
+ llvmFunc.setSubprogram(program);
+ builder.finalizeSubprogram(program);
+}
+
+//===----------------------------------------------------------------------===//
+// Locations
+//===----------------------------------------------------------------------===//
+
+/// Translate the given location to an llvm debug location.
+const llvm::DILocation *
+DebugTranslation::translateLoc(Location loc, llvm::DILocalScope *scope) {
+ if (!compileUnit)
+ return nullptr;
+ return translateLoc(loc, scope, /*inlinedAt=*/nullptr);
+}
+
+/// Translate the given location to an llvm DebugLoc.
+const llvm::DILocation *
+DebugTranslation::translateLoc(Location loc, llvm::DILocalScope *scope,
+ const llvm::DILocation *inlinedAt) {
+ // LLVM doesn't have a representation for unknown.
+ if (!scope || loc.isa<UnknownLoc>())
+ return nullptr;
+
+ // Check for a cached instance.
+ const auto *&llvmLoc = locationToLoc[std::make_pair(loc, scope)];
+ if (llvmLoc)
+ return llvmLoc;
+
+ switch (loc->getKind()) {
+ case StandardAttributes::CallSiteLocation: {
+ auto callLoc = loc.dyn_cast<CallSiteLoc>();
+
+ // For callsites, the caller is fed as the inlinedAt for the callee.
+ const auto *callerLoc = translateLoc(callLoc.getCaller(), scope, inlinedAt);
+ llvmLoc = translateLoc(callLoc.getCallee(), scope, callerLoc);
+ break;
+ }
+ case StandardAttributes::FileLineColLocation: {
+ auto fileLoc = loc.dyn_cast<FileLineColLoc>();
+ auto *file = translateFile(fileLoc.getFilename());
+ auto *fileScope = builder.createLexicalBlockFile(scope, file);
+ llvmLoc = llvm::DILocation::get(llvmCtx, fileLoc.getLine(),
+ fileLoc.getColumn(), fileScope,
+ const_cast<llvm::DILocation *>(inlinedAt));
+ break;
+ }
+ case StandardAttributes::FusedLocation: {
+ auto fusedLoc = loc.dyn_cast<FusedLoc>();
+ ArrayRef<Location> locations = fusedLoc.getLocations();
+
+ // For fused locations, merge each of the nodes.
+ llvmLoc = translateLoc(locations.front(), scope, inlinedAt);
+ for (Location locIt : locations.drop_front()) {
+ llvmLoc = llvm::DILocation::getMergedLocation(
+ llvmLoc, translateLoc(locIt, scope, inlinedAt));
+ }
+ break;
+ }
+ case StandardAttributes::NameLocation:
+ llvmLoc = translateLoc(loc.cast<NameLoc>().getChildLoc(), scope, inlinedAt);
+ break;
+ case StandardAttributes::OpaqueLocation:
+ llvmLoc = translateLoc(loc.cast<OpaqueLoc>().getFallbackLocation(), scope,
+ inlinedAt);
+ break;
+ default:
+ llvm_unreachable("unknown location kind");
+ }
+ return llvmLoc;
+}
+
+/// Create an llvm debug file for the given file path.
+llvm::DIFile *DebugTranslation::translateFile(StringRef fileName) {
+ auto *&file = fileMap[fileName];
+ if (file)
+ return file;
+
+ // Make sure the current working directory is up-to-date.
+ if (currentWorkingDir.empty())
+ llvm::sys::fs::current_path(currentWorkingDir);
+
+ StringRef directory = currentWorkingDir;
+ SmallString<128> dirBuf;
+ SmallString<128> fileBuf;
+ if (llvm::sys::path::is_absolute(fileName)) {
+ // Strip the common prefix (if it is more than just "/") from current
+ // directory and FileName for a more space-efficient encoding.
+ auto fileIt = llvm::sys::path::begin(fileName);
+ auto fileE = llvm::sys::path::end(fileName);
+ auto curDirIt = llvm::sys::path::begin(directory);
+ auto curDirE = llvm::sys::path::end(directory);
+ for (; curDirIt != curDirE && *curDirIt == *fileIt; ++curDirIt, ++fileIt)
+ llvm::sys::path::append(dirBuf, *curDirIt);
+ if (std::distance(llvm::sys::path::begin(directory), curDirIt) == 1) {
+ // Don't strip the common prefix if it is only the root "/" since that
+ // would make LLVM diagnostic locations confusing.
+ directory = StringRef();
+ } else {
+ for (; fileIt != fileE; ++fileIt)
+ llvm::sys::path::append(fileBuf, *fileIt);
+ directory = dirBuf;
+ fileName = fileBuf;
+ }
+ }
+ return (file = builder.createFile(fileName, directory));
+}
--- /dev/null
+//===- DebugTranslation.h - MLIR to LLVM Debug conversion -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the translation between an MLIR debug information and
+// the corresponding LLVMIR representation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_
+#define MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_
+
+#include "mlir/IR/Location.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/DIBuilder.h"
+
+namespace mlir {
+class Operation;
+
+namespace LLVM {
+class LLVMFuncOp;
+
+namespace detail {
+class DebugTranslation {
+public:
+ DebugTranslation(Operation *module, llvm::Module &llvmModule);
+
+ /// Finalize the translation of debug information.
+ void finalize();
+
+ /// Translate the given location to an llvm debug location.
+ const llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope);
+
+ /// Translate the debug information for the given function.
+ void translate(LLVMFuncOp func, llvm::Function &llvmFunc);
+
+private:
+ /// Translate the given location to an llvm debug location with the given
+ /// scope and inlinedAt parameters.
+ const llvm::DILocation *translateLoc(Location loc, llvm::DILocalScope *scope,
+ const llvm::DILocation *inlinedAt);
+
+ /// Create an llvm debug file for the given file path.
+ llvm::DIFile *translateFile(StringRef fileName);
+
+ /// A mapping between mlir location+scope and the corresponding llvm debug
+ /// metadata.
+ DenseMap<std::pair<Location, llvm::DILocalScope *>, const llvm::DILocation *>
+ locationToLoc;
+
+ /// A mapping between filename and llvm debug file.
+ /// TODO(riverriddle) Change this to DenseMap<Identifier, ...> when we can
+ /// access the Identifier filename in FileLineColLoc.
+ llvm::StringMap<llvm::DIFile *> fileMap;
+
+ /// A string containing the current working directory of the compiler.
+ SmallString<256> currentWorkingDir;
+
+ /// Debug information fields.
+ llvm::DIBuilder builder;
+ llvm::LLVMContext &llvmCtx;
+ llvm::DICompileUnit *compileUnit;
+};
+
+} // end namespace detail
+} // end namespace LLVM
+} // end namespace mlir
+
+#endif // MLIR_LIB_TARGET_LLVMIR_DEBUGTRANSLATION_H_
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+#include "DebugTranslation.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Module.h"
using namespace mlir;
using namespace mlir::LLVM;
+using namespace mlir::LLVM::detail;
#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
llvm_unreachable("incorrect atomic ordering");
}
+ModuleTranslation::ModuleTranslation(Operation *module,
+ std::unique_ptr<llvm::Module> llvmModule)
+ : mlirModule(module), llvmModule(std::move(llvmModule)),
+ debugTranslation(
+ std::make_unique<DebugTranslation>(module, *this->llvmModule)) {
+ assert(satisfiesLLVMModule(mlirModule) &&
+ "mlirModule should honor LLVM's module semantics.");
+}
+ModuleTranslation::~ModuleTranslation() {}
+
/// Given a single MLIR operation, create the corresponding LLVM IR operation
/// using the `builder`. LLVM IR Builder does not have a generic interface so
/// this has to be a long chain of `if`s calling different functions with a
/// are not connected to the source basic blocks, which may not exist yet.
LogicalResult ModuleTranslation::convertBlock(Block &bb, bool ignoreArguments) {
llvm::IRBuilder<> builder(blockMapping[&bb]);
+ auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
// Before traversing operations, make block arguments available through
// value remapping and PHI nodes, but do not add incoming edges for the PHI
// Traverse operations.
for (auto &op : bb) {
+ // Set the current debug location within the builder.
+ builder.SetCurrentDebugLocation(
+ debugTranslation->translateLoc(op.getLoc(), subprogram));
+
if (failed(convertOperation(op, builder)))
return failure();
}
blockMapping.clear();
valueMapping.clear();
llvm::Function *llvmFunc = functionMapping.lookup(func.getName());
+
+ // Translate the debug information for this function.
+ debugTranslation->translate(func, *llvmFunc);
+
// Add function arguments to the value remapping table.
// If there was noalias info then we decorate each argument accordingly.
unsigned int argIdx = 0;
using namespace mlir;
namespace {
-struct StripDebugInfo : public FunctionPass<StripDebugInfo> {
- void runOnFunction() override;
+struct StripDebugInfo : public OperationPass<StripDebugInfo> {
+ void runOnOperation() override;
};
} // end anonymous namespace
-void StripDebugInfo::runOnFunction() {
- FuncOp func = getFunction();
+void StripDebugInfo::runOnOperation() {
+ // Strip the debug info from all operations.
auto unknownLoc = UnknownLoc::get(&getContext());
-
- // Strip the debug info from the function and its operations.
- func.setLoc(unknownLoc);
- func.walk([&](Operation *op) { op->setLoc(unknownLoc); });
+ getOperation()->walk([&](Operation *op) { op->setLoc(unknownLoc); });
}
/// Creates a pass to strip debug information from a function.
-std::unique_ptr<OpPassBase<FuncOp>> mlir::createStripDebugInfoPass() {
+std::unique_ptr<Pass> mlir::createStripDebugInfoPass() {
return std::make_unique<StripDebugInfo>();
}
static PassRegistration<StripDebugInfo>
- pass("strip-debuginfo", "Strip debug info from functions and operations");
+ pass("strip-debuginfo", "Strip debug info from all operations");
--- /dev/null
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK-LABEL: define void @func_no_debug()
+// CHECK-NOT: !dbg
+llvm.func @func_no_debug() {
+ llvm.return loc(unknown)
+} loc(unknown)
+
+// CHECK-LABEL: define void @func_with_debug()
+// CHECK-SAME: !dbg ![[FUNC_LOC:[0-9]+]]
+llvm.func @func_with_debug() {
+ // CHECK: call void @func_no_debug()
+ // CHECK-NOT: !dbg
+ llvm.call @func_no_debug() : () -> () loc(unknown)
+
+ // CHECK: call void @func_no_debug(), !dbg ![[CALLSITE_LOC:[0-9]+]]
+ llvm.call @func_no_debug() : () -> () loc(callsite("mysource.cc":3:4 at "mysource.cc":5:6))
+
+ // CHECK: call void @func_no_debug(), !dbg ![[FILE_LOC:[0-9]+]]
+ llvm.call @func_no_debug() : () -> () loc("foo.mlir":1:2)
+
+ // CHECK: call void @func_no_debug(), !dbg ![[NAMED_LOC:[0-9]+]]
+ llvm.call @func_no_debug() : () -> () loc("named"("foo.mlir":10:10))
+
+ // CHECK: call void @func_no_debug(), !dbg ![[FUSED_LOC:[0-9]+]]
+ llvm.call @func_no_debug() : () -> () loc(fused[callsite("mysource.cc":1:1 at "mysource.cc":5:6), "mysource.cc":1:1])
+
+ llvm.return
+} loc("foo.mlir":1:1)
+
+// CHECK-DAG: ![[FUNC_LOC]] = distinct !DISubprogram{{.*}}, line: 1
+// CHECK-DAG: ![[CALLSITE_LOC]] = !DILocation(line: 3, column: 4,
+// CHECK-DAG: ![[FILE_LOC]] = !DILocation(line: 1, column: 2,
+// CHECK-DAG: ![[NAMED_LOC]] = !DILocation(line: 10, column: 10
+// CHECK-DAG: ![[FUSED_LOC]] = !DILocation(line: 1, column: 1
// phi nodes, scalar type conversion, arithmetic operations.
//
-// CHECK-LABEL: define void @empty() {
+// CHECK-LABEL: define void @empty()
// CHECK-NEXT: ret void
// CHECK-NEXT: }
llvm.func @empty() {
llvm.func @body(!llvm.i64)
-// CHECK-LABEL: define void @simple_loop() {
+// CHECK-LABEL: define void @simple_loop()
llvm.func @simple_loop() {
// CHECK: br label %[[SIMPLE_bb1:[0-9]+]]
llvm.br ^bb1
llvm.return
}
-// CHECK-LABEL: define void @simple_caller() {
+// CHECK-LABEL: define void @simple_caller()
// CHECK-NEXT: call void @simple_loop()
// CHECK-NEXT: ret void
// CHECK-NEXT: }
// return
//}
-// CHECK-LABEL: define void @ml_caller() {
+// CHECK-LABEL: define void @ml_caller()
// CHECK-NEXT: call void @simple_loop()
// CHECK-NEXT: call void @more_imperfectly_nested_loops()
// CHECK-NEXT: ret void
// CHECK-LABEL: declare i32 @other(i64, i32)
llvm.func @other(!llvm.i64, !llvm.i32) -> !llvm.i32
-// CHECK-LABEL: define i32 @func_args(i32 {{%.*}}, i32 {{%.*}}) {
+// CHECK-LABEL: define i32 @func_args(i32 {{%.*}}, i32 {{%.*}})
// CHECK-NEXT: br label %[[ARGS_bb1:[0-9]+]]
llvm.func @func_args(%arg0: !llvm.i32, %arg1: !llvm.i32) -> !llvm.i32 {
%0 = llvm.mlir.constant(0 : i32) : !llvm.i32
// CHECK: declare void @post(i64)
llvm.func @post(!llvm.i64)
-// CHECK-LABEL: define void @imperfectly_nested_loops() {
+// CHECK-LABEL: define void @imperfectly_nested_loops()
// CHECK-NEXT: br label %[[IMPER_bb1:[0-9]+]]
llvm.func @imperfectly_nested_loops() {
llvm.br ^bb1
llvm.func @body3(!llvm.i64, !llvm.i64)
// A complete function transformation check.
-// CHECK-LABEL: define void @more_imperfectly_nested_loops() {
+// CHECK-LABEL: define void @more_imperfectly_nested_loops()
// CHECK-NEXT: br label %1
// CHECK: 1: ; preds = %0
// CHECK-NEXT: br label %2
llvm.return
}
-// CHECK-LABEL: define { float*, i64 } @memref_args_rets({ float* } {{%.*}}, { float*, i64 } {{%.*}}, { float*, i64 } {{%.*}}) {
+// CHECK-LABEL: define { float*, i64 } @memref_args_rets({ float* } {{%.*}}, { float*, i64 } {{%.*}}, { float*, i64 } {{%.*}})
llvm.func @memref_args_rets(%arg0: !llvm<"{ float* }">, %arg1: !llvm<"{ float*, i64 }">, %arg2: !llvm<"{ float*, i64 }">) -> !llvm<"{ float*, i64 }"> {
%0 = llvm.mlir.constant(7 : index) : !llvm.i64
// CHECK-NEXT: %{{[0-9]+}} = call i64 @get_index()
llvm.func @get_f32() -> !llvm.float
llvm.func @get_memref() -> !llvm<"{ float*, i64, i64 }">
-// CHECK-LABEL: define { i64, float, { float*, i64, i64 } } @multireturn() {
+// CHECK-LABEL: define { i64, float, { float*, i64, i64 } } @multireturn()
llvm.func @multireturn() -> !llvm<"{ i64, float, { float*, i64, i64 } }"> {
%0 = llvm.call @get_i64() : () -> !llvm.i64
%1 = llvm.call @get_f32() : () -> !llvm.float
}
-// CHECK-LABEL: define void @multireturn_caller() {
+// CHECK-LABEL: define void @multireturn_caller()
llvm.func @multireturn_caller() {
// CHECK-NEXT: %1 = call { i64, float, { float*, i64, i64 } } @multireturn()
// CHECK-NEXT: [[ret0:%[0-9]+]] = extractvalue { i64, float, { float*, i64, i64 } } %1, 0
llvm.return
}
-// CHECK-LABEL: define <4 x float> @vector_ops(<4 x float> {{%.*}}, <4 x i1> {{%.*}}, <4 x i64> {{%.*}}) {
+// CHECK-LABEL: define <4 x float> @vector_ops(<4 x float> {{%.*}}, <4 x i1> {{%.*}}, <4 x i64> {{%.*}})
llvm.func @vector_ops(%arg0: !llvm<"<4 x float>">, %arg1: !llvm<"<4 x i1>">, %arg2: !llvm<"<4 x i64>">) -> !llvm<"<4 x float>"> {
%0 = llvm.mlir.constant(dense<4.200000e+01> : vector<4xf32>) : !llvm<"<4 x float>">
// CHECK-NEXT: %4 = fadd <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
// Indirect function calls
//
-// CHECK-LABEL: define void @indirect_const_call(i64 {{%.*}}) {
+// CHECK-LABEL: define void @indirect_const_call(i64 {{%.*}})
llvm.func @indirect_const_call(%arg0: !llvm.i64) {
// CHECK-NEXT: call void @body(i64 %0)
%0 = llvm.mlir.constant(@body) : !llvm<"void (i64)*">
llvm.return
}
-// CHECK-LABEL: define i32 @indirect_call(i32 (float)* {{%.*}}, float {{%.*}}) {
+// CHECK-LABEL: define i32 @indirect_call(i32 (float)* {{%.*}}, float {{%.*}})
llvm.func @indirect_call(%arg0: !llvm<"i32 (float)*">, %arg1: !llvm.float) -> !llvm.i32 {
// CHECK-NEXT: %3 = call i32 %0(float %1)
%0 = llvm.call %arg0(%arg1) : (!llvm.float) -> !llvm.i32
// predecessor more than once.
//
-// CHECK-LABEL: define void @cond_br_arguments(i1 {{%.*}}, i1 {{%.*}}) {
+// CHECK-LABEL: define void @cond_br_arguments(i1 {{%.*}}, i1 {{%.*}})
llvm.func @cond_br_arguments(%arg0: !llvm.i1, %arg1: !llvm.i1) {
// CHECK-NEXT: br i1 %0, label %3, label %5
llvm.cond_br %arg0, ^bb1(%arg0 : !llvm.i1), ^bb2
llvm.br ^bb1(%arg1 : !llvm.i1)
}
-// CHECK-LABEL: define void @llvm_noalias(float* noalias {{%*.}}) {
+// CHECK-LABEL: define void @llvm_noalias(float* noalias {{%*.}})
llvm.func @llvm_noalias(%arg0: !llvm<"float*"> {llvm.noalias = true}) {
llvm.return
}
#include "mlir/Pass/PassManager.h"
#include "mlir/Support/JitRunner.h"
#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/Passes.h"
#include "cuda.h"
pm.addPass(createGpuKernelOutliningPass());
auto &kernelPm = pm.nest<gpu::GPUModuleOp>();
+ kernelPm.addPass(createStripDebugInfoPass());
kernelPm.addPass(createLowerGpuOpsToNVVMOpsPass());
kernelPm.addPass(createConvertGPUKernelToCubinPass(&compilePtxToCubin));
pm.addPass(createLowerToLLVMPass());