diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -178,14 +178,14 @@ def LLVM_LifetimeStartOp : LLVM_LifetimeBaseOp<"lifetime.start"> { // Custom builder to convert the size argument to an attribute. string mlirBuilder = [{ - $_builder.create( + $_op = $_builder.create( $_location, $_int_attr($size), $ptr); }]; } def LLVM_LifetimeEndOp : LLVM_LifetimeBaseOp<"lifetime.end"> { // Custom builder to convert the size argument to an attribute. string mlirBuilder = [{ - $_builder.create( + $_op = $_builder.create( $_location, $_int_attr($size), $ptr); }]; } @@ -286,7 +286,7 @@ // convertible to MLIR. auto *dbgIntr = cast(inst); if (dbgIntr->getExpression()->getNumElements() == 0) - $_builder.create<$_qualCppClassName>($_location, + $_op = $_builder.create<$_qualCppClassName>($_location, $}] # argName # [{, $_var_attr($varInfo)); }]; let assemblyFormat = [{ @@ -484,7 +484,7 @@ $rows, $columns); }]; string mlirBuilder = [{ - $_builder.create( + $_op = $_builder.create( $_location, $matrix, $data, $stride, $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns)); }]; @@ -579,7 +579,7 @@ $value, $data, llvm::Align($alignment), $mask); }]; string mlirBuilder = [{ - $_builder.create($_location, + $_op = $_builder.create($_location, $value, $data, $mask, $_int_attr($alignment)); }]; list llvmArgIndices = [0, 1, 3, 2]; @@ -621,7 +621,7 @@ $value, $ptrs, llvm::Align($alignment), $mask); }]; string mlirBuilder = [{ - $_builder.create($_location, + $_op = $_builder.create($_location, $value, $ptrs, $mask, $_int_attr($alignment)); }]; list llvmArgIndices = [0, 1, 3, 2]; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -234,12 +234,16 @@ // of the MLIR operation argument with the given name, or if the // name matches the result name, by a reference to store the // result of the newly created MLIR operation to; + // - $_op - substituted by a reference to store the newly created MLIR + // operation (only for MLIR operations that return no result); // - $_int_attr - substituted by a call to an integer attribute matcher; // - $_var_attr - substituted by a call to a variable attribute matcher; // - $_resultType - substituted with the MLIR result type; // - $_location - substituted with the MLIR location; // - $_builder - substituted with the MLIR builder; // - $_qualCppClassName - substitiuted with the MLIR operation class name. + // Always either store a reference to the result of the newly created + // operation, or to the operation itself if it does not return a result. // Additionally, `$$` can be used to produce the dollar character. string mlirBuilder = ""; @@ -388,7 +392,7 @@ $_location, resultTypes, *mlirOperands); }] # !if(!gt(requiresFastmath, 0), "moduleImport.setFastmathFlagsAttr(inst, op);", "") - # !if(!gt(numResults, 0), "$res = op;", "(void)op;"); + # !if(!gt(numResults, 0), "$res = op;", "$_op = op;"); } // Base class for LLVM intrinsic operations, should not be used directly. Places diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -400,7 +400,7 @@ # setAliasScopeMetadataCode; // FIXME: Import attributes. string mlirBuilder = [{ - $_builder.create($_location, $value, $addr); + $_op = $_builder.create($_location, $value, $addr); }]; let builders = [ OpBuilder<(ins "Value":$value, "Value":$addr, @@ -830,7 +830,7 @@ moduleImport.convertValues(llvmOperands); if (failed(mlirOperands)) return failure(); - $_builder.create($_location, *mlirOperands); + $_op = $_builder.create($_location, *mlirOperands); }]; } @@ -841,7 +841,7 @@ string llvmInstName = "Resume"; string llvmBuilder = [{ builder.CreateResume($value); }]; string mlirBuilder = [{ - $_builder.create($_location, $value); + $_op = $_builder.create($_location, $value); }]; } def LLVM_UnreachableOp : LLVM_TerminatorOp<"unreachable"> { @@ -849,7 +849,7 @@ string llvmInstName = "Unreachable"; string llvmBuilder = [{ builder.CreateUnreachable(); }]; string mlirBuilder = [{ - $_builder.create($_location); + $_op = $_builder.create($_location); }]; } @@ -1559,7 +1559,7 @@ }]; string mlirBuilder = [{ llvm::FenceInst *fenceInst = cast(inst); - $_builder.create( + $_op = $_builder.create( $_location, getLLVMAtomicOrdering(fenceInst->getOrdering()), getLLVMSyncScope(fenceInst)); diff --git a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h --- a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h +++ b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h @@ -52,10 +52,24 @@ return failure(); } + /// Hook for derived dialect interfaces to implement the import of metadata + /// into MLIR. Attaches the converted metadata kind and node to the provided + /// operation. + virtual LogicalResult + setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, + Operation *op, LLVM::ModuleImport &moduleImport) const { + return failure(); + } + /// Hook for derived dialect interfaces to publish the supported intrinsics. /// As every LLVM IR intrinsic has a unique integer identifier, the function /// returns the list of supported intrinsic identifiers. virtual ArrayRef getSupportedIntrinsics() const { return {}; } + + /// Hook for derived dialect interfaces to publish the supported metadata + /// kinds. As every metadata kind has a unique integer identifier, the + /// function returns the list of supported metadata identifiers. + virtual ArrayRef getSupportedMetadata() const { return {}; } }; /// Interface collection for the import of LLVM IR that dispatches to a concrete @@ -67,10 +81,10 @@ public: using Base::Base; - /// Queries all dialect interfaces to build a map from intrinsic identifiers - /// to the dialect interface that supports importing the intrinsic. Returns - /// failure if multiple dialect interfaces translate the same LLVM IR - /// intrinsic. + /// Queries all registered dialect interfaces for the supported LLVM IR + /// intrinsic and metadata kinds and builds the dispatch tables for the + /// conversion. Returns failure if multiple dialect interfaces translate the + /// same LLVM IR intrinsic. LogicalResult initializeImport() { for (const LLVMImportDialectInterface &iface : *this) { // Verify the supported intrinsics have not been mapped before. @@ -89,6 +103,9 @@ // Add a mapping for all supported intrinsic identifiers. for (unsigned id : iface.getSupportedIntrinsics()) intrinsicToDialect[id] = iface.getDialect(); + // Add a mapping for all supported metadata kinds. + for (unsigned kind : iface.getSupportedMetadata()) + metadataToDialect[kind].push_back(iface.getDialect()); } return success(); @@ -115,8 +132,41 @@ return intrinsicToDialect.count(id); } + /// Attaches the given LLVM metadata to the imported operation if a conversion + /// to one or more MLIR dialect attributes exists and succeeds. Returns + /// success if at least one of the conversions is successful and failure if + /// all of them fail. + LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, + llvm::MDNode *node, Operation *op, + LLVM::ModuleImport &moduleImport) const { + // Lookup the dialect interfaces for the given metadata. + auto it = metadataToDialect.find(kind); + if (it == metadataToDialect.end()) + return failure(); + + // Dispatch the conversion to the dialect interfaces. + bool isSuccess = false; + for (Dialect *dialect : it->getSecond()) { + const LLVMImportDialectInterface *iface = getInterfaceFor(dialect); + assert(iface && "expected to find a dialect interface"); + if (succeeded( + iface->setMetadataAttrs(builder, kind, node, op, moduleImport))) + isSuccess = true; + } + + // Returns failure if all conversions fail. + return success(isSuccess); + } + + /// Returns true if the given LLVM IR metadata is convertible to an MLIR + /// attribute. + bool isConvertibleMetadata(unsigned kind) { + return metadataToDialect.count(kind); + } + private: DenseMap intrinsicToDialect; + DenseMap> metadataToDialect; }; } // namespace mlir diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -46,9 +46,9 @@ ModuleImport(ModuleOp mlirModule, std::unique_ptr llvmModule); /// Calls the LLVMImportInterface initialization that queries the registered - /// dialect interfaces for the supported LLVM IR intrinsics and builds the - /// dispatch table. Returns failure if multiple dialect interfaces translate - /// the same LLVM IR intrinsic. + /// dialect interfaces for the supported LLVM IR intrinsics and metadata kinds + /// and builds the dispatch tables. Returns failure if multiple dialect + /// interfaces translate the same LLVM IR intrinsic. LogicalResult initializeImportInterface() { return iface.initializeImport(); } /// Converts all functions of the LLVM module to MLIR functions. @@ -72,6 +72,35 @@ /// Returns the MLIR value mapped to the given LLVM value. Value lookupValue(llvm::Value *value) { return valueMapping.lookup(value); } + /// Stores a mapping between an LLVM instruction and the imported MLIR + /// operation if the operation returns no result. Asserts if the operation + /// returns a result and should be added to valueMapping instead. + void mapNoResultOp(llvm::Instruction *inst, Operation *mlir) { + mapNoResultOp(inst) = mlir; + } + + /// Provides write-once access to store the MLIR operation corresponding to + /// the given LLVM instruction if the operation returns no result. Asserts if + /// the operation returns a result and should be added to valueMapping + /// instead. + Operation *&mapNoResultOp(llvm::Instruction *inst) { + Operation *&mlir = noResultOpMapping[inst]; + assert(inst->getType()->isVoidTy() && + "attempting to map an operation that returns a result"); + assert(mlir == nullptr && + "attempting to map an operation that is already mapped"); + return mlir; + } + + /// Returns the MLIR operation mapped to the given LLVM instruction. Queries + /// valueMapping and noResultOpMapping to support operations with and without + /// result. + Operation *lookupOperation(llvm::Instruction *inst) { + if (Value value = lookupValue(inst)) + return value.getDefiningOp(); + return noResultOpMapping.lookup(inst); + } + /// Stores the mapping between an LLVM block and its MLIR counterpart. void mapBlock(llvm::BasicBlock *llvm, Block *mlir) { auto result = blockMapping.try_emplace(llvm, mlir); @@ -127,6 +156,7 @@ /// Clears the block and value mapping before processing a new region. void clearBlockAndValueMapping() { valueMapping.clear(); + noResultOpMapping.clear(); blockMapping.clear(); } /// Sets the constant insertion point to the start of the given block. @@ -146,8 +176,14 @@ /// counterpart exists. Otherwise, returns failure. LogicalResult convertInstruction(OpBuilder &odsBuilder, llvm::Instruction *inst); + /// Converts the metadata attached to the original instruction `inst` if + /// a dialect interfaces supports the specific kind of metadata and attaches + /// the resulting dialect attributes to the converted operation `op`. Emits a + /// warning if the conversion of a supported metadata kind fails. + void setNonDebugMetadataAttrs(llvm::Instruction *inst, Operation *op); /// Imports `inst` and populates valueMapping[inst] with the result of the - /// imported operation. + /// imported operation or noResultOpMapping[inst] with the imported operation + /// if it has no result. LogicalResult processInstruction(llvm::Instruction *inst); /// Converts the `branch` arguments in the order of the phi's found in /// `target` and appends them to the `blockArguments` to attach to the @@ -205,6 +241,10 @@ DenseMap blockMapping; /// Function-local mapping between original and imported values. DenseMap valueMapping; + /// Function-local mapping between original instructions and imported + /// operations for all operations that return no result. All operations that + /// return a result have a valueMapping entry instead. + DenseMap noResultOpMapping; /// Uniquing map of GlobalVariables. DenseMap globals; /// The stateful type translator (contains named structs). diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp @@ -65,6 +65,51 @@ return failure(); } +/// Returns the list of LLVM IR metadata kinds that are convertible to MLIR LLVM +/// dialect attributes. +static ArrayRef getSupportedMetadataImpl() { + static const SmallVector convertibleMetadata = { + llvm::LLVMContext::MD_prof // profiling metadata + }; + return convertibleMetadata; +} + +/// Attaches the given profiling metadata to the imported operation if a +/// conversion to an MLIR profiling attribute exists and succeeds. Returns +/// failure otherwise. +static LogicalResult setProfilingAttrs(OpBuilder &builder, llvm::MDNode *node, + Operation *op, + LLVM::ModuleImport &moduleImport) { + // Return success for empty metadata nodes since there is nothing to import. + if (!node->getNumOperands()) + return success(); + + // Return failure for non-"branch_weights" metadata. + auto *name = dyn_cast(node->getOperand(0)); + if (!name || !name->getString().equals("branch_weights")) + return failure(); + + // Copy the branch weights to an array. + SmallVector branchWeights; + branchWeights.reserve(node->getNumOperands() - 1); + for (unsigned i = 1, e = node->getNumOperands(); i != e; ++i) { + llvm::ConstantInt *branchWeight = + llvm::mdconst::extract(node->getOperand(i)); + branchWeights.push_back(branchWeight->getZExtValue()); + } + + // Attach the branch weights to the operations that support it. + if (auto condBrOp = dyn_cast(op)) { + condBrOp.setBranchWeightsAttr(builder.getI32VectorAttr(branchWeights)); + return success(); + } + if (auto switchOp = dyn_cast(op)) { + switchOp.setBranchWeightsAttr(builder.getI32VectorAttr(branchWeights)); + return success(); + } + return failure(); +} + namespace { /// Implementation of the dialect interface that converts operations belonging @@ -80,11 +125,31 @@ return convertIntrinsicImpl(builder, inst, moduleImport); } + /// Attaches the given LLVM metadata to the imported operation if a conversion + /// to an LLVM dialect attribute exists and succeeds. Returns failure + /// otherwise. + LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, + llvm::MDNode *node, Operation *op, + LLVM::ModuleImport &moduleImport) const final { + // Call metadata specific handlers. + if (kind == llvm::LLVMContext::MD_prof) + return setProfilingAttrs(builder, node, op, moduleImport); + + // A handler for a supported metadata kind is missing. + llvm_unreachable("unknown metadata type"); + } + /// Returns the list of LLVM IR intrinsic identifiers that are convertible to /// MLIR LLVM dialect intrinsics. ArrayRef getSupportedIntrinsics() const final { return getSupportedIntrinsicsImpl(); } + + /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR + /// LLVM dialect attributes. + ArrayRef getSupportedMetadata() const final { + return getSupportedMetadataImpl(); + } }; } // namespace diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" using namespace mlir; @@ -331,6 +332,20 @@ return success(); } +void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst, + Operation *op) { + SmallVector> allMetadata; + inst->getAllMetadataOtherThanDebugLoc(allMetadata); + for (auto &[kind, node] : allMetadata) { + if (!iface.isConvertibleMetadata(kind)) + continue; + if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) { + Location loc = debugImporter->translateLoc(inst->getDebugLoc()); + emitWarning(loc) << "unhandled metadata (" << kind << ") " << diag(*inst); + } + } +} + void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const { auto iface = cast(op); @@ -625,6 +640,8 @@ // resulting in a conflicting `valueMapping` entry. llvm::Instruction *inst = constExpr->getAsInstruction(); auto guard = llvm::make_scope_exit([&]() { + assert(noResultOpMapping.find(inst) == noResultOpMapping.end() && + "expected constant expression to return a result"); valueMapping.erase(inst); inst->deleteValue(); }); @@ -833,17 +850,19 @@ succBlockArgs.push_back(blockArgs); } - if (brInst->isConditional()) { - FailureOr condition = convertValue(brInst->getCondition()); - if (failed(condition)) - return failure(); - builder.create(loc, *condition, succBlocks.front(), - succBlockArgs.front(), succBlocks.back(), - succBlockArgs.back()); - } else { - builder.create(loc, succBlockArgs.front(), - succBlocks.front()); + if (!brInst->isConditional()) { + auto brOp = builder.create(loc, succBlockArgs.front(), + succBlocks.front()); + mapNoResultOp(inst, brOp); + return success(); } + FailureOr condition = convertValue(brInst->getCondition()); + if (failed(condition)) + return failure(); + auto condBrOp = builder.create( + loc, *condition, succBlocks.front(), succBlockArgs.front(), + succBlocks.back(), succBlockArgs.back()); + mapNoResultOp(inst, condBrOp); return success(); } if (inst->getOpcode() == llvm::Instruction::Switch) { @@ -874,9 +893,10 @@ caseBlocks[it.index()] = lookupBlock(succBB); } - builder.create(loc, *condition, lookupBlock(defaultBB), - defaultBlockArgs, caseValues, caseBlocks, - caseOperandRefs); + auto switchOp = builder.create( + loc, *condition, lookupBlock(defaultBB), defaultBlockArgs, caseValues, + caseBlocks, caseOperandRefs); + mapNoResultOp(inst, switchOp); return success(); } if (inst->getOpcode() == llvm::Instruction::PHI) { @@ -903,6 +923,8 @@ setFastmathFlagsAttr(inst, callOp); if (!callInst->getType()->isVoidTy()) mapValue(inst, callOp.getResult()); + else + mapNoResultOp(inst, callOp); return success(); } if (inst->getOpcode() == llvm::Instruction::LandingPad) { @@ -918,9 +940,9 @@ } Type type = convertType(lpInst->getType()); - Value res = + auto lpOp = builder.create(loc, type, lpInst->isCleanup(), operands); - mapValue(inst, res); + mapValue(inst, lpOp); return success(); } if (inst->getOpcode() == llvm::Instruction::Invoke) { @@ -951,6 +973,8 @@ } if (!invokeInst->getType()->isVoidTy()) mapValue(inst, invokeOp.getResults().front()); + else + mapNoResultOp(inst, invokeOp); return success(); } if (inst->getOpcode() == llvm::Instruction::GetElementPtr) { @@ -973,9 +997,9 @@ } Type type = convertType(inst->getType()); - Value res = builder.create(loc, type, sourceElementType, *basePtr, - indices, gepInst->isInBounds()); - mapValue(inst, res); + auto gepOp = builder.create(loc, type, sourceElementType, *basePtr, + indices, gepInst->isInBounds()); + mapValue(inst, gepOp); return success(); } @@ -1131,6 +1155,16 @@ for (llvm::Instruction &inst : *bb) { if (failed(processInstruction(&inst))) return failure(); + + // Set the non-debug metadata attributes on the imported operation and emit + // a warning if an instruction other than a phi instruction is dropped + // during the import. + if (Operation *op = lookupOperation(&inst)) { + setNonDebugMetadataAttrs(&inst, op); + } else if (inst.getOpcode() != llvm::Instruction::PHI) { + Location loc = debugImporter->translateLoc(inst.getDebugLoc()); + emitWarning(loc) << "dropped instruction " << diag(inst); + } } return success(); } diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -1,6 +1,6 @@ ; RUN: not mlir-translate -import-llvm -split-input-file %s 2>&1 | FileCheck %s -; CHECK: unhandled instruction indirectbr i8* %dst, [label %bb1, label %bb2] +; CHECK: error: unhandled instruction indirectbr i8* %dst, [label %bb1, label %bb2] define i32 @unhandled_instruction(i8* %dst) { indirectbr i8* %dst, [label %bb1, label %bb2] bb1: @@ -19,7 +19,7 @@ ; // ----- -; CHECK: unhandled constant i8* blockaddress(@unhandled_constant, %bb1) +; CHECK: error: unhandled constant i8* blockaddress(@unhandled_constant, %bb1) define i8* @unhandled_constant() { bb1: ret i8* blockaddress(@unhandled_constant, %bb1) @@ -29,8 +29,41 @@ declare void @llvm.gcroot(ptr %arg0, ptr %arg1) -; CHECK: unhandled intrinsic call void @llvm.gcroot(ptr %arg0, ptr %arg1) +; CHECK: error: unhandled intrinsic call void @llvm.gcroot(ptr %arg0, ptr %arg1) define void @unhandled_intrinsic(ptr %arg0, ptr %arg1) { call void @llvm.gcroot(ptr %arg0, ptr %arg1) ret void } + +; // ----- + +; CHECK: warning: unhandled metadata (2) br i1 %arg1, label %bb1, label %bb2, !prof !0 +define i64 @cond_br(i1 %arg1, i64 %arg2) { +entry: + br i1 %arg1, label %bb1, label %bb2, !prof !0 +bb1: + ret i64 %arg2 +bb2: + ret i64 %arg2 +} + +!0 = !{!"unknown metadata"} + +; // ----- + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +; CHECK: warning: dropped instruction call void @llvm.dbg.value(metadata i64 %arg1, metadata !3, metadata !DIExpression(DW_OP_plus_uconst, 42, DW_OP_stack_value)), !dbg !5 +define void @dropped_instruction(i64 %arg1) { + call void @llvm.dbg.value(metadata i64 %arg1, metadata !3, metadata !DIExpression(DW_OP_plus_uconst, 42, DW_OP_stack_value)), !dbg !5 + ret void +} + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) +!2 = !DIFile(filename: "debug-info.ll", directory: "/") +!3 = !DILocalVariable(scope: !4, name: "arg", file: !2, line: 1, arg: 1, align: 32); +!4 = distinct !DISubprogram(name: "intrinsic", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1) +!5 = !DILocation(line: 1, column: 2, scope: !4) diff --git a/mlir/test/Target/LLVMIR/Import/profiling-metadata.ll b/mlir/test/Target/LLVMIR/Import/profiling-metadata.ll new file mode 100644 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/profiling-metadata.ll @@ -0,0 +1,35 @@ +; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s + +; CHECK-LABEL: @cond_br +define i64 @cond_br(i1 %arg1, i64 %arg2) { +entry: + ; CHECK: llvm.cond_br + ; CHECK-SAME: weights(dense<[0, 3]> : vector<2xi32>) + br i1 %arg1, label %bb1, label %bb2, !prof !0 +bb1: + ret i64 %arg2 +bb2: + ret i64 %arg2 +} + +!0 = !{!"branch_weights", i32 0, i32 3} + +; // ----- + +; CHECK-LABEL: @simple_switch( +define i32 @simple_switch(i32 %arg1) { + ; CHECK: llvm.switch + ; CHECK: {branch_weights = dense<[42, 3, 5]> : vector<3xi32>} + switch i32 %arg1, label %bbd [ + i32 0, label %bb1 + i32 9, label %bb2 + ], !prof !0 +bb1: + ret i32 %arg1 +bb2: + ret i32 %arg1 +bbd: + ret i32 %arg1 +} + +!0 = !{!"branch_weights", i32 42, i32 3, i32 5} diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp --- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp @@ -262,6 +262,8 @@ if (op.getNumResults() != 1) return emitError(record, "expected op to have one result"); bs << "moduleImport.mapValue(inst)"; + } else if (name == "_op") { + bs << "moduleImport.mapNoResultOp(inst)"; } else if (name == "_int_attr") { bs << "moduleImport.matchIntegerAttr"; } else if (name == "_var_attr") {