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,15 +178,19 @@ def LLVM_LifetimeStartOp : LLVM_LifetimeBaseOp<"lifetime.start"> { // Custom builder to convert the size argument to an attribute. string mlirBuilder = [{ - $_builder.create( + auto op = $_builder.create( $_location, $_int_attr($size), $ptr); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } def LLVM_LifetimeEndOp : LLVM_LifetimeBaseOp<"lifetime.end"> { // Custom builder to convert the size argument to an attribute. string mlirBuilder = [{ - $_builder.create( + auto op = $_builder.create( $_location, $_int_attr($size), $ptr); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } @@ -285,9 +289,12 @@ // TODO: Stop dropping debug intrinsics once debug expressions are // convertible to MLIR. auto *dbgIntr = cast(inst); - if (dbgIntr->getExpression()->getNumElements() == 0) - $_builder.create<$_qualCppClassName>($_location, + if (dbgIntr->getExpression()->getNumElements() == 0) { + auto op = $_builder.create<$_qualCppClassName>($_location, $}] # argName # [{, $_var_attr($varInfo)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + } }]; let assemblyFormat = [{ qualified($varInfo) `=` $}] # argName # @@ -395,8 +402,11 @@ }]; let mlirBuilder = [{ bool allowReassoc = inst->getFastMathFlags().allowReassoc(); - $res = $_builder.create<$_qualCppClassName>($_location, + auto op = $_builder.create<$_qualCppClassName>($_location, $_resultType, $start_value, $input, allowReassoc); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -450,9 +460,12 @@ $columns); }]; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, $data, $stride, $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -484,9 +497,11 @@ $rows, $columns); }]; string mlirBuilder = [{ - $_builder.create( + auto op = $_builder.create( $_location, $matrix, $data, $stride, $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } @@ -507,9 +522,12 @@ $rhs_columns); }]; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, $lhs, $rhs, $_int_attr($lhs_rows), $_int_attr($lhs_columns), $_int_attr($rhs_columns)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -527,9 +545,12 @@ $matrix, $rows, $columns); }]; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, $matrix, $_int_attr($rows), $_int_attr($columns)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -560,8 +581,11 @@ $_resultType, $data, llvm::Align($alignment), $mask, $pass_thru[0]); }]; string mlirBuilder = [{ - $res = $_builder.create($_location, + auto op = $_builder.create($_location, $_resultType, $data, $mask, $pass_thru, $_int_attr($alignment)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; list llvmArgIndices = [0, 2, 3, 1]; } @@ -579,8 +603,10 @@ $value, $data, llvm::Align($alignment), $mask); }]; string mlirBuilder = [{ - $_builder.create($_location, + auto op = $_builder.create($_location, $value, $data, $mask, $_int_attr($alignment)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; list llvmArgIndices = [0, 1, 3, 2]; } @@ -602,8 +628,11 @@ $_resultType, $ptrs, llvm::Align($alignment), $mask, $pass_thru[0]); }]; string mlirBuilder = [{ - $res = $_builder.create($_location, + auto op = $_builder.create($_location, $_resultType, $ptrs, $mask, $pass_thru, $_int_attr($alignment)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; list llvmArgIndices = [0, 2, 3, 1]; } @@ -621,8 +650,10 @@ $value, $ptrs, llvm::Align($alignment), $mask); }]; string mlirBuilder = [{ - $_builder.create($_location, + auto op = $_builder.create($_location, $value, $ptrs, $mask, $_int_attr($alignment)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; 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 @@ -386,6 +386,8 @@ }] # !if(!gt(numResults, 0), "{$_resultType};", "{};") # [{ auto op = $_builder.create<$_qualCppClassName>( $_location, resultTypes, *mlirOperands); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }] # !if(!gt(requiresFastmath, 0), "moduleImport.setFastmathFlagsAttr(inst, op);", "") # !if(!gt(numResults, 0), "$res = op;", "(void)op;"); 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 @@ -50,7 +50,10 @@ LLVM_ArithmeticOpBase { let arguments = commonArgs; string mlirBuilder = [{ - $res = $_builder.create<$_qualCppClassName>($_location, $lhs, $rhs); + auto op = $_builder.create<$_qualCppClassName>($_location, $lhs, $rhs); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } class LLVM_FloatArithmeticOp($_location, $lhs, $rhs); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); moduleImport.setFastmathFlagsAttr(inst, op); $res = op; }]; @@ -82,6 +87,8 @@ string llvmInstName = instName; string mlirBuilder = [{ auto op = $_builder.create<$_qualCppClassName>($_location, $operand); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); moduleImport.setFastmathFlagsAttr(inst, op); $res = op; }]; @@ -129,8 +136,11 @@ }]; string mlirBuilder = [{ auto *iCmpInst = cast(inst); - $res = $_builder.create<$_qualCppClassName>( + auto op = $_builder.create<$_qualCppClassName>( $_location, getICmpPredicate(iCmpInst->getPredicate()), $lhs, $rhs); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; // Set the $predicate index to -1 to indicate there is no matching operand // and decrement the following indices. @@ -157,6 +167,8 @@ auto *fCmpInst = cast(inst); auto op = $_builder.create<$_qualCppClassName>( $_location, getFCmpPredicate(fCmpInst->getPredicate()), $lhs, $rhs); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); moduleImport.setFastmathFlagsAttr(inst, op); $res = op; }]; @@ -230,8 +242,11 @@ Type allocatedType = moduleImport.convertType(allocaInst->getAllocatedType()); unsigned alignment = allocaInst->getAlign().value(); - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, allocatedType, $arraySize, alignment); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; let builders = [ OpBuilder<(ins "Type":$resultType, "Value":$arraySize, @@ -365,7 +380,10 @@ }]; // FIXME: Import attributes. string mlirBuilder = [{ - $res = $_builder.create($_location, $_resultType, $addr); + auto op = $_builder.create($_location, $_resultType, $addr); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; let builders = [ OpBuilder<(ins "Value":$addr, CArg<"unsigned", "0">:$alignment, @@ -400,7 +418,9 @@ # setAliasScopeMetadataCode; // FIXME: Import attributes. string mlirBuilder = [{ - $_builder.create($_location, $value, $addr); + auto op = $_builder.create($_location, $value, $addr); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; let builders = [ OpBuilder<(ins "Value":$value, "Value":$addr, @@ -422,8 +442,11 @@ let assemblyFormat = "$arg attr-dict `:` type($arg) `to` type($res)"; string llvmInstName = instName; string mlirBuilder = [{ - $res = $_builder.create<$_qualCppClassName>( + auto op = $_builder.create<$_qualCppClassName>( $_location, $_resultType, $arg); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } def LLVM_BitcastOp : LLVM_CastOp<"bitcast", "BitCast", @@ -587,8 +610,11 @@ $res = builder.CreateExtractElement($vector, $position); }]; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $vector, $position); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -621,8 +647,11 @@ }]; string mlirBuilder = [{ auto *evInst = cast(inst); - $res = $_builder.create($_location, + auto op = $_builder.create($_location, $container, getPositionFromIndices(evInst->getIndices())); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -652,8 +681,11 @@ $res = builder.CreateInsertElement($vector, $value, $position); }]; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $vector, $value, $position); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -684,8 +716,11 @@ }]; string mlirBuilder = [{ auto *ivInst = cast(inst); - $res = $_builder.create($_location, + auto op = $_builder.create($_location, $container, $value, getPositionFromIndices(ivInst->getIndices())); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -721,8 +756,11 @@ string mlirBuilder = [{ auto *svInst = cast(inst); SmallVector mask(svInst->getShuffleMask()); - $res = $_builder.create( + auto op = $_builder.create( $_location, $v1, $v2, mask); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -738,8 +776,11 @@ let assemblyFormat = "operands attr-dict `:` type($condition) `,` type($res)"; string llvmInstName = "Select"; string mlirBuilder = [{ - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, $condition, $trueValue, $falseValue); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } def LLVM_FreezeOp : LLVM_Op<"freeze", [SameOperandsAndResultType]> { @@ -750,7 +791,10 @@ string llvmInstName = "Freeze"; string llvmBuilder = "$res = builder.CreateFreeze($val);"; string mlirBuilder = [{ - $res = $_builder.create($_location, $val); + auto op = $_builder.create($_location, $val); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -830,7 +874,9 @@ moduleImport.convertValues(llvmOperands); if (failed(mlirOperands)) return failure(); - $_builder.create($_location, *mlirOperands); + auto op = $_builder.create($_location, *mlirOperands); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } @@ -841,7 +887,9 @@ string llvmInstName = "Resume"; string llvmBuilder = [{ builder.CreateResume($value); }]; string mlirBuilder = [{ - $_builder.create($_location, $value); + auto op = $_builder.create($_location, $value); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } def LLVM_UnreachableOp : LLVM_TerminatorOp<"unreachable"> { @@ -849,7 +897,9 @@ string llvmInstName = "Unreachable"; string llvmBuilder = [{ builder.CreateUnreachable(); }]; string mlirBuilder = [{ - $_builder.create($_location); + auto op = $_builder.create($_location); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; } @@ -1503,9 +1553,12 @@ }]; string mlirBuilder = [{ auto *atomicInst = cast(inst); - $res = $_builder.create($_location, $_resultType, + auto op = $_builder.create($_location, $_resultType, getLLVMAtomicBinOp(atomicInst->getOperation()), $ptr, $val, getLLVMAtomicOrdering(atomicInst->getOrdering())); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; // Only $ptr and $val are llvm instruction operands. list llvmArgIndices = [-1, 0, 1, -1]; @@ -1541,10 +1594,13 @@ }]; string mlirBuilder = [{ auto *cmpXchgInst = cast(inst); - $res = $_builder.create( + auto op = $_builder.create( $_location, $_resultType, $ptr, $cmp, $val, getLLVMAtomicOrdering(cmpXchgInst->getSuccessOrdering()), getLLVMAtomicOrdering(cmpXchgInst->getFailureOrdering())); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); + $res = op; }]; } @@ -1559,10 +1615,12 @@ }]; string mlirBuilder = [{ llvm::FenceInst *fenceInst = cast(inst); - $_builder.create( + auto op = $_builder.create( $_location, getLLVMAtomicOrdering(fenceInst->getOrdering()), getLLVMSyncScope(fenceInst)); + // Set non-debug metadata attributes. + moduleImport.setNonDebugMetadataAttrs(inst, op); }]; let hasCustomAssemblyFormat = 1; let hasVerifier = 1; 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,8 +52,21 @@ 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. virtual ArrayRef getSupportedIntrinsics() const { return {}; } + + /// Hook for derived dialect interfaces to publish the supported metadata + /// kinds. + virtual ArrayRef getSupportedMetadata() const { return {}; } }; /// Interface collection for the import of LLVM IR that dispatches to a concrete @@ -65,12 +78,13 @@ 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) { + // Query all supported intrinsics and enforce a unique mapping. for (unsigned id : iface.getSupportedIntrinsics()) { if (intrinsicToDialect.count(id)) { Location loc = UnknownLoc::get(iface.getContext()); @@ -83,6 +97,9 @@ } intrinsicToDialect[id] = iface.getDialect(); } + // Query all supported metadata kinds. + for (unsigned kind : iface.getSupportedMetadata()) + metadataToDialect[kind].push_back(iface.getDialect()); } return success(); @@ -109,8 +126,40 @@ 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 + /// failure otherwise. + LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, + llvm::MDNode *node, Operation *op, + LLVM::ModuleImport &moduleImport) const { + // Lookup the dialect interfaces for the given metadata. + SmallVector dialects = metadataToDialect.lookup(kind); + if (dialects.empty()) + return failure(); + + // Dispatch the conversion to the dialect interfaces. + bool isSuccess = false; + for (Dialect *dialect : dialects) { + 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. @@ -118,6 +118,12 @@ /// Imports `globalVar` as a GlobalOp, creating it if it doesn't exist. GlobalOp processGlobal(llvm::GlobalVariable *globalVar); + /// 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); + /// Sets the fastmath flags attribute for the imported operation `op` given /// the original instruction `inst`. Asserts if the operation does not /// implement the fastmath interface. diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMImport.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMImport.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMImport.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMImport.cpp @@ -65,6 +65,52 @@ 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. + // TODO: Avoid instruction specific code using a branch weight interface. + 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 +126,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); @@ -833,17 +848,21 @@ 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()); + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(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()); + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, condBrOp); return success(); } if (inst->getOpcode() == llvm::Instruction::Switch) { @@ -874,9 +893,11 @@ 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); + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, switchOp); return success(); } if (inst->getOpcode() == llvm::Instruction::PHI) { @@ -900,6 +921,8 @@ } else { callOp = builder.create(loc, types, operands); } + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, callOp); setFastmathFlagsAttr(inst, callOp); if (!callInst->getType()->isVoidTy()) mapValue(inst, callOp.getResult()); @@ -918,9 +941,11 @@ } Type type = convertType(lpInst->getType()); - Value res = + auto lpOp = builder.create(loc, type, lpInst->isCleanup(), operands); - mapValue(inst, res); + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, lpOp); + mapValue(inst, lpOp); return success(); } if (inst->getOpcode() == llvm::Instruction::Invoke) { @@ -949,6 +974,8 @@ loc, types, operands, lookupBlock(invokeInst->getNormalDest()), normalArgs, lookupBlock(invokeInst->getUnwindDest()), unwindArgs); } + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, invokeOp); if (!invokeInst->getType()->isVoidTy()) mapValue(inst, invokeOp.getResults().front()); return success(); @@ -973,9 +1000,11 @@ } 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()); + // Set non-debug metadata attributes. + setNonDebugMetadataAttrs(inst, gepOp); + mapValue(inst, gepOp); 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 @@ -34,3 +34,17 @@ call void @llvm.gcroot(ptr %arg0, ptr %arg1) ret void } + +; // ----- + +; CHECK: 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"} diff --git a/mlir/test/Target/LLVMIR/Import/metadata.ll b/mlir/test/Target/LLVMIR/Import/metadata.ll new file mode 100644 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/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}