[Mlir-commits] [mlir] 0cf0663 - [mlir][llvm] Make the import of LLVM IR metadata extensible.

Tobias Gysi llvmlistbot at llvm.org
Tue Jan 3 05:50:17 PST 2023


Author: Tobias Gysi
Date: 2023-01-03T14:47:25+01:00
New Revision: 0cf066392f685f251102d2e7c29178a755f867fe

URL: https://github.com/llvm/llvm-project/commit/0cf066392f685f251102d2e7c29178a755f867fe
DIFF: https://github.com/llvm/llvm-project/commit/0cf066392f685f251102d2e7c29178a755f867fe.diff

LOG: [mlir][llvm] Make the import of LLVM IR metadata extensible.

This revision extends the LLVMImportDialectInterface to make the import
of LLVM IR instruction-level metadata extensible. It extends the
signature of the existing dialect interface to provide a method to
import specific metadata kinds and attach them to the imported
operation. The conversion function can rely on the ModuleImport class
to perform support tasks.

The revision implements the second part of the
"extensible llvm ir import" rfc:
https://discourse.llvm.org/t/rfc-extensible-llvm-ir-import/67256/6

The interface method names changed a bit compared to the suggested
design. The hook to set the instruction level metadata is now called
setMetadataAttrs and takes the metadata kind as an additional parameter.
We do not hand in the original LLVM IR instruction since it is not used
at this point. Importing named module-level meta data can be added in a
later stage after gaining some experience with this extension mechanism.

Depends on D140374

Reviewed By: ftynse, Dinistro

Differential Revision: https://reviews.llvm.org/D140556

Added: 
    mlir/test/Target/LLVMIR/Import/profiling-metadata.ll

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
    mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
    mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
    mlir/include/mlir/Target/LLVMIR/ModuleImport.h
    mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
    mlir/lib/Target/LLVMIR/ModuleImport.cpp
    mlir/test/Target/LLVMIR/Import/import-failure.ll
    mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
index 0e478ce46fab1..1ce8e80bc65bb 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
@@ -178,14 +178,14 @@ class LLVM_LifetimeBaseOp<string opName> : LLVM_ZeroResultIntrOp<opName> {
 def LLVM_LifetimeStartOp : LLVM_LifetimeBaseOp<"lifetime.start"> {
   // Custom builder to convert the size argument to an attribute.
   string mlirBuilder = [{
-    $_builder.create<LLVM::LifetimeStartOp>(
+    $_op = $_builder.create<LLVM::LifetimeStartOp>(
       $_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<LLVM::LifetimeEndOp>(
+    $_op = $_builder.create<LLVM::LifetimeEndOp>(
       $_location, $_int_attr($size), $ptr);
   }];
 }
@@ -286,7 +286,7 @@ class LLVM_DbgIntrOp<string name, string argName> : LLVM_IntrOp<name, [], [], []
     // convertible to MLIR.
     auto *dbgIntr = cast<llvm::DbgVariableIntrinsic>(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 @@ def LLVM_MatrixColumnMajorStoreOp : LLVM_ZeroResultIntrOp<"matrix.column.major.s
       $rows, $columns);
   }];
   string mlirBuilder = [{
-    $_builder.create<LLVM::MatrixColumnMajorStoreOp>(
+    $_op = $_builder.create<LLVM::MatrixColumnMajorStoreOp>(
       $_location, $matrix, $data, $stride,
       $_int_attr($isVolatile), $_int_attr($rows), $_int_attr($columns));
   }];
@@ -579,7 +579,7 @@ def LLVM_MaskedStoreOp : LLVM_ZeroResultIntrOp<"masked.store"> {
       $value, $data, llvm::Align($alignment), $mask);
   }];
   string mlirBuilder = [{
-    $_builder.create<LLVM::MaskedStoreOp>($_location,
+    $_op = $_builder.create<LLVM::MaskedStoreOp>($_location,
       $value, $data, $mask, $_int_attr($alignment));
   }];
   list<int> llvmArgIndices = [0, 1, 3, 2];
@@ -621,7 +621,7 @@ def LLVM_masked_scatter : LLVM_ZeroResultIntrOp<"masked.scatter"> {
       $value, $ptrs, llvm::Align($alignment), $mask);
   }];
   string mlirBuilder = [{
-    $_builder.create<LLVM::masked_scatter>($_location,
+    $_op = $_builder.create<LLVM::masked_scatter>($_location,
       $value, $ptrs, $mask, $_int_attr($alignment));
   }];
   list<int> llvmArgIndices = [0, 1, 3, 2];

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
index 048281f146e06..c85df7ddacbae 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -234,12 +234,16 @@ class LLVM_OpBase<Dialect dialect, string mnemonic, list<Trait> traits = []> :
   //             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 @@ class LLVM_IntrOpBase<Dialect dialect, string opName, string enumName,
       $_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
index 2e46a7180201b..714209c675ade 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -400,7 +400,7 @@ def LLVM_StoreOp : LLVM_Op<"store">, MemoryOpWithAlignmentAndAttributes {
      # setAliasScopeMetadataCode;
   // FIXME: Import attributes.
   string mlirBuilder = [{
-    $_builder.create<LLVM::StoreOp>($_location, $value, $addr);
+    $_op = $_builder.create<LLVM::StoreOp>($_location, $value, $addr);
   }];
   let builders = [
     OpBuilder<(ins "Value":$value, "Value":$addr,
@@ -830,7 +830,7 @@ def LLVM_ReturnOp : LLVM_TerminatorOp<"return", [Pure, ReturnLike]> {
       moduleImport.convertValues(llvmOperands);
     if (failed(mlirOperands))
       return failure();
-    $_builder.create<LLVM::ReturnOp>($_location, *mlirOperands);
+    $_op = $_builder.create<LLVM::ReturnOp>($_location, *mlirOperands);
   }];
 }
 
@@ -841,7 +841,7 @@ def LLVM_ResumeOp : LLVM_TerminatorOp<"resume"> {
   string llvmInstName = "Resume";
   string llvmBuilder = [{ builder.CreateResume($value); }];
   string mlirBuilder = [{
-    $_builder.create<LLVM::ResumeOp>($_location, $value);
+    $_op = $_builder.create<LLVM::ResumeOp>($_location, $value);
   }];
 }
 def LLVM_UnreachableOp : LLVM_TerminatorOp<"unreachable"> {
@@ -849,7 +849,7 @@ def LLVM_UnreachableOp : LLVM_TerminatorOp<"unreachable"> {
   string llvmInstName = "Unreachable";
   string llvmBuilder = [{ builder.CreateUnreachable(); }];
   string mlirBuilder = [{
-    $_builder.create<LLVM::UnreachableOp>($_location);
+    $_op = $_builder.create<LLVM::UnreachableOp>($_location);
   }];
 }
 
@@ -1559,7 +1559,7 @@ def LLVM_FenceOp : LLVM_Op<"fence"> {
   }];
   string mlirBuilder = [{
     llvm::FenceInst *fenceInst = cast<llvm::FenceInst>(inst);
-    $_builder.create<LLVM::FenceOp>(
+    $_op = $_builder.create<LLVM::FenceOp>(
       $_location,
       getLLVMAtomicOrdering(fenceInst->getOrdering()),
       getLLVMSyncScope(fenceInst));

diff  --git a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
index 014107a4526bc..9f8da83ae9c20 100644
--- a/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
+++ b/mlir/include/mlir/Target/LLVMIR/LLVMImportInterface.h
@@ -52,10 +52,24 @@ class LLVMImportDialectInterface
     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<unsigned> 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<unsigned> getSupportedMetadata() const { return {}; }
 };
 
 /// Interface collection for the import of LLVM IR that dispatches to a concrete
@@ -67,10 +81,10 @@ class LLVMImportInterface
 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 @@ class LLVMImportInterface
       // 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 @@ class LLVMImportInterface
     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<unsigned, Dialect *> intrinsicToDialect;
+  DenseMap<unsigned, SmallVector<Dialect *, 1>> metadataToDialect;
 };
 
 } // namespace mlir

diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 903160f09e714..27e2b297e8f31 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -46,9 +46,9 @@ class ModuleImport {
   ModuleImport(ModuleOp mlirModule, std::unique_ptr<llvm::Module> 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 @@ class ModuleImport {
   /// 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 @@ class ModuleImport {
   /// 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 @@ class ModuleImport {
   /// 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 @@ class ModuleImport {
   DenseMap<llvm::BasicBlock *, Block *> blockMapping;
   /// Function-local mapping between original and imported values.
   DenseMap<llvm::Value *, Value> 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<llvm::Instruction *, Operation *> noResultOpMapping;
   /// Uniquing map of GlobalVariables.
   DenseMap<llvm::GlobalVariable *, GlobalOp> 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
index ff6ed967d964e..493be27bfbddc 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp
@@ -65,6 +65,51 @@ static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
   return failure();
 }
 
+/// Returns the list of LLVM IR metadata kinds that are convertible to MLIR LLVM
+/// dialect attributes.
+static ArrayRef<unsigned> getSupportedMetadataImpl() {
+  static const SmallVector<unsigned> 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<llvm::MDString>(node->getOperand(0));
+  if (!name || !name->getString().equals("branch_weights"))
+    return failure();
+
+  // Copy the branch weights to an array.
+  SmallVector<int32_t> branchWeights;
+  branchWeights.reserve(node->getNumOperands() - 1);
+  for (unsigned i = 1, e = node->getNumOperands(); i != e; ++i) {
+    llvm::ConstantInt *branchWeight =
+        llvm::mdconst::extract<llvm::ConstantInt>(node->getOperand(i));
+    branchWeights.push_back(branchWeight->getZExtValue());
+  }
+
+  // Attach the branch weights to the operations that support it.
+  if (auto condBrOp = dyn_cast<CondBrOp>(op)) {
+    condBrOp.setBranchWeightsAttr(builder.getI32VectorAttr(branchWeights));
+    return success();
+  }
+  if (auto switchOp = dyn_cast<SwitchOp>(op)) {
+    switchOp.setBranchWeightsAttr(builder.getI32VectorAttr(branchWeights));
+    return success();
+  }
+  return failure();
+}
+
 namespace {
 
 /// Implementation of the dialect interface that converts operations belonging
@@ -80,11 +125,31 @@ class LLVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
     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<unsigned> getSupportedIntrinsics() const final {
     return getSupportedIntrinsicsImpl();
   }
+
+  /// Returns the list of LLVM IR metadata kinds that are convertible to MLIR
+  /// LLVM dialect attributes.
+  ArrayRef<unsigned> getSupportedMetadata() const final {
+    return getSupportedMetadataImpl();
+  }
 };
 } // namespace
 

diff  --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 77828c99398f7..750e967eb956a 100644
--- 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 @@ LogicalResult ModuleImport::convertFunctions() {
   return success();
 }
 
+void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
+                                            Operation *op) {
+  SmallVector<std::pair<unsigned, llvm::MDNode *>> 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<FastmathFlagsInterface>(op);
@@ -625,6 +640,8 @@ FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
     // 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 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
       succBlockArgs.push_back(blockArgs);
     }
 
-    if (brInst->isConditional()) {
-      FailureOr<Value> condition = convertValue(brInst->getCondition());
-      if (failed(condition))
-        return failure();
-      builder.create<LLVM::CondBrOp>(loc, *condition, succBlocks.front(),
-                                     succBlockArgs.front(), succBlocks.back(),
-                                     succBlockArgs.back());
-    } else {
-      builder.create<LLVM::BrOp>(loc, succBlockArgs.front(),
-                                 succBlocks.front());
+    if (!brInst->isConditional()) {
+      auto brOp = builder.create<LLVM::BrOp>(loc, succBlockArgs.front(),
+                                             succBlocks.front());
+      mapNoResultOp(inst, brOp);
+      return success();
     }
+    FailureOr<Value> condition = convertValue(brInst->getCondition());
+    if (failed(condition))
+      return failure();
+    auto condBrOp = builder.create<LLVM::CondBrOp>(
+        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 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
       caseBlocks[it.index()] = lookupBlock(succBB);
     }
 
-    builder.create<SwitchOp>(loc, *condition, lookupBlock(defaultBB),
-                             defaultBlockArgs, caseValues, caseBlocks,
-                             caseOperandRefs);
+    auto switchOp = builder.create<SwitchOp>(
+        loc, *condition, lookupBlock(defaultBB), defaultBlockArgs, caseValues,
+        caseBlocks, caseOperandRefs);
+    mapNoResultOp(inst, switchOp);
     return success();
   }
   if (inst->getOpcode() == llvm::Instruction::PHI) {
@@ -903,6 +923,8 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
     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 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
     }
 
     Type type = convertType(lpInst->getType());
-    Value res =
+    auto lpOp =
         builder.create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
-    mapValue(inst, res);
+    mapValue(inst, lpOp);
     return success();
   }
   if (inst->getOpcode() == llvm::Instruction::Invoke) {
@@ -951,6 +973,8 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
     }
     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 @@ LogicalResult ModuleImport::convertInstruction(OpBuilder &odsBuilder,
     }
 
     Type type = convertType(inst->getType());
-    Value res = builder.create<GEPOp>(loc, type, sourceElementType, *basePtr,
-                                      indices, gepInst->isInBounds());
-    mapValue(inst, res);
+    auto gepOp = builder.create<GEPOp>(loc, type, sourceElementType, *basePtr,
+                                       indices, gepInst->isInBounds());
+    mapValue(inst, gepOp);
     return success();
   }
 
@@ -1131,6 +1155,16 @@ LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
   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
index cefb6bbb6b441..740f055e1eaac 100644
--- 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 @@ define i32 @unhandled_value(i32 %arg0) {
 
 ; // -----
 
-; 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 @@ bb1:
 
 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
index 0000000000000..402271a6a2b51
--- /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
index 4e59c8b44422a..1aa5232f9671d 100644
--- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
+++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp
@@ -262,6 +262,8 @@ static LogicalResult emitOneMLIRBuilder(const Record &record, raw_ostream &os,
       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") {


        


More information about the Mlir-commits mailing list