[mlir] use the new stateful LLVM type translator by default
authorAlex Zinenko <zinenko@google.com>
Wed, 5 Aug 2020 12:44:03 +0000 (14:44 +0200)
committerAlex Zinenko <zinenko@google.com>
Wed, 5 Aug 2020 22:36:33 +0000 (00:36 +0200)
Previous type model in the LLVM dialect did not support identified structure
types properly and therefore could use stateless translations implemented as
free functions. The new model supports identified structs and must keep track
of the identified structure types present in the target context (LLVMContext or
MLIRContext) to avoid creating duplicate structs due to LLVM's type
auto-renaming. Expose the stateful type translation classes and use them during
translation, storing the state as part of ModuleTranslation.

Drop the test type translation mechanism that is no longer necessary and update
the tests to exercise type translation as part of the main translation flow.

Update the code in vector-to-LLVM dialect conversion that relied on stateless
translation to use the new class in a stateless manner.

Reviewed By: rriddle

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

13 files changed:
mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/include/mlir/Target/LLVMIR/TypeTranslation.h
mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/lib/Target/LLVMIR/TypeTranslation.cpp
mlir/test/Target/import.ll
mlir/test/Target/llvmir-types.mlir
mlir/test/lib/CMakeLists.txt
mlir/test/lib/Target/CMakeLists.txt [deleted file]
mlir/test/lib/Target/TestLLVMTypeTranslation.cpp [deleted file]
mlir/tools/mlir-translate/mlir-translate.cpp

index 6b771f8..2853ef6 100644 (file)
@@ -48,12 +48,6 @@ struct LLVMTypeStorage;
 struct LLVMDialectImpl;
 } // namespace detail
 
-/// Converts an MLIR LLVM dialect type to LLVM IR type. Note that this function
-/// exists exclusively for the purpose of gradual transition to the first-party
-/// modeling of LLVM types. It should not be used outside MLIR-to-LLVM
-/// translation.
-llvm::Type *convertLLVMType(LLVMType type);
-
 ///// Ops /////
 #define GET_OP_CLASSES
 #include "mlir/Dialect/LLVMIR/LLVMOps.h.inc"
index 61f8f9f..8b67c24 100644 (file)
@@ -19,6 +19,7 @@
 #include "mlir/IR/Block.h"
 #include "mlir/IR/Module.h"
 #include "mlir/IR/Value.h"
+#include "mlir/Target/LLVMIR/TypeTranslation.h"
 
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/BasicBlock.h"
@@ -127,6 +128,9 @@ private:
   /// Mappings between llvm.mlir.global definitions and corresponding globals.
   DenseMap<Operation *, llvm::GlobalValue *> globalsMapping;
 
+  /// A stateful object used to translate types.
+  TypeToLLVMIRTranslator typeTranslator;
+
 protected:
   /// Mappings between original and translated values, used for lookups.
   llvm::StringMap<llvm::Function *> functionMapping;
index 3ab962b..71924b0 100644 (file)
 #ifndef MLIR_TARGET_LLVMIR_TYPETRANSLATION_H
 #define MLIR_TARGET_LLVMIR_TYPETRANSLATION_H
 
+#include <memory>
+
 namespace llvm {
+class DataLayout;
 class LLVMContext;
 class Type;
 } // namespace llvm
@@ -27,8 +30,49 @@ namespace LLVM {
 
 class LLVMType;
 
-llvm::Type *translateTypeToLLVMIR(LLVMType type, llvm::LLVMContext &context);
-LLVMType translateTypeFromLLVMIR(llvm::Type *type, MLIRContext &context);
+namespace detail {
+class TypeToLLVMIRTranslatorImpl;
+class TypeFromLLVMIRTranslatorImpl;
+} // namespace detail
+
+/// Utility class to translate MLIR LLVM dialect types to LLVM IR. Stores the
+/// translation state, in particular any identified structure types that can be
+/// reused in further translation.
+class TypeToLLVMIRTranslator {
+public:
+  TypeToLLVMIRTranslator(llvm::LLVMContext &context);
+  ~TypeToLLVMIRTranslator();
+
+  /// Returns the perferred alignment for the type given the data layout. Note
+  /// that this will perform type conversion and store its results for future
+  /// uses.
+  // TODO: this should be removed when MLIR has proper data layout.
+  unsigned getPreferredAlignment(LLVM::LLVMType type,
+                                 const llvm::DataLayout &layout);
+
+  /// Translates the given MLIR LLVM dialect type to LLVM IR.
+  llvm::Type *translateType(LLVM::LLVMType type);
+
+private:
+  /// Private implementation.
+  std::unique_ptr<detail::TypeToLLVMIRTranslatorImpl> impl;
+};
+
+/// Utility class to translate LLVM IR types to the MLIR LLVM dialect. Stores
+/// the translation state, in particular any identified structure types that are
+/// reused across translations.
+class TypeFromLLVMIRTranslator {
+public:
+  TypeFromLLVMIRTranslator(MLIRContext &context);
+  ~TypeFromLLVMIRTranslator();
+
+  /// Translates the given LLVM IR type to the MLIR LLVM dialect.
+  LLVM::LLVMType translateType(llvm::Type *type);
+
+private:
+  /// Private implementation.
+  std::unique_ptr<detail::TypeFromLLVMIRTranslatorImpl> impl;
+};
 
 } // namespace LLVM
 } // namespace mlir
index 23373f5..8f5ec9e 100644 (file)
@@ -126,11 +126,12 @@ LogicalResult getMemRefAlignment(LLVMTypeConverter &typeConverter, T op,
   if (!elementTy)
     return failure();
 
-  auto dataLayout = typeConverter.getDialect()->getLLVMModule().getDataLayout();
-  // TODO: this should be abstracted away to avoid depending on translation.
-  align = dataLayout.getPrefTypeAlignment(LLVM::translateTypeToLLVMIR(
-      elementTy.cast<LLVM::LLVMType>(),
-      typeConverter.getDialect()->getLLVMContext()));
+  // TODO: this should use the MLIR data layout when it becomes available and
+  // stop depending on translation.
+  LLVM::LLVMDialect *dialect = typeConverter.getDialect();
+  align = LLVM::TypeToLLVMIRTranslator(dialect->getLLVMContext())
+              .getPreferredAlignment(elementTy.cast<LLVM::LLVMType>(),
+                                     dialect->getLLVMModule().getDataLayout());
   return success();
 }
 
index 77897d6..54d5275 100644 (file)
@@ -16,6 +16,7 @@
 #include "mlir/IR/Module.h"
 #include "mlir/IR/StandardTypes.h"
 #include "mlir/Target/LLVMIR.h"
+#include "mlir/Target/LLVMIR/TypeTranslation.h"
 #include "mlir/Translation.h"
 
 #include "llvm/IR/Attributes.h"
@@ -48,7 +49,8 @@ class Importer {
 public:
   Importer(MLIRContext *context, ModuleOp module)
       : b(context), context(context), module(module),
-        unknownLoc(FileLineColLoc::get("imported-bitcode", 0, 0, context)) {
+        unknownLoc(FileLineColLoc::get("imported-bitcode", 0, 0, context)),
+        typeTranslator(*context) {
     b.setInsertionPointToStart(module.getBody());
     dialect = context->getRegisteredDialect<LLVMDialect>();
   }
@@ -129,6 +131,8 @@ private:
   Location unknownLoc;
   /// Cached dialect.
   LLVMDialect *dialect;
+  /// The stateful type translator (contains named structs).
+  LLVM::TypeFromLLVMIRTranslator typeTranslator;
 };
 } // namespace
 
@@ -149,79 +153,16 @@ Location Importer::processDebugLoc(const llvm::DebugLoc &loc,
 }
 
 LLVMType Importer::processType(llvm::Type *type) {
-  switch (type->getTypeID()) {
-  case llvm::Type::FloatTyID:
-    return LLVMType::getFloatTy(dialect);
-  case llvm::Type::DoubleTyID:
-    return LLVMType::getDoubleTy(dialect);
-  case llvm::Type::IntegerTyID:
-    return LLVMType::getIntNTy(dialect, type->getIntegerBitWidth());
-  case llvm::Type::PointerTyID: {
-    LLVMType elementType = processType(type->getPointerElementType());
-    if (!elementType)
-      return nullptr;
-    return elementType.getPointerTo(type->getPointerAddressSpace());
-  }
-  case llvm::Type::ArrayTyID: {
-    LLVMType elementType = processType(type->getArrayElementType());
-    if (!elementType)
-      return nullptr;
-    return LLVMType::getArrayTy(elementType, type->getArrayNumElements());
-  }
-  case llvm::Type::ScalableVectorTyID: {
-    emitError(unknownLoc) << "scalable vector types not supported";
-    return nullptr;
-  }
-  case llvm::Type::FixedVectorTyID: {
-    auto *typeVTy = llvm::cast<llvm::FixedVectorType>(type);
-    LLVMType elementType = processType(typeVTy->getElementType());
-    if (!elementType)
-      return nullptr;
-    return LLVMType::getVectorTy(elementType, typeVTy->getNumElements());
-  }
-  case llvm::Type::VoidTyID:
-    return LLVMType::getVoidTy(dialect);
-  case llvm::Type::FP128TyID:
-    return LLVMType::getFP128Ty(dialect);
-  case llvm::Type::X86_FP80TyID:
-    return LLVMType::getX86_FP80Ty(dialect);
-  case llvm::Type::StructTyID: {
-    SmallVector<LLVMType, 4> elementTypes;
-    elementTypes.reserve(type->getStructNumElements());
-    for (unsigned i = 0, e = type->getStructNumElements(); i != e; ++i) {
-      LLVMType ty = processType(type->getStructElementType(i));
-      if (!ty)
-        return nullptr;
-      elementTypes.push_back(ty);
-    }
-    return LLVMType::getStructTy(dialect, elementTypes,
-                                 cast<llvm::StructType>(type)->isPacked());
-  }
-  case llvm::Type::FunctionTyID: {
-    llvm::FunctionType *fty = cast<llvm::FunctionType>(type);
-    SmallVector<LLVMType, 4> paramTypes;
-    for (unsigned i = 0, e = fty->getNumParams(); i != e; ++i) {
-      LLVMType ty = processType(fty->getParamType(i));
-      if (!ty)
-        return nullptr;
-      paramTypes.push_back(ty);
-    }
-    LLVMType result = processType(fty->getReturnType());
-    if (!result)
-      return nullptr;
+  if (LLVMType result = typeTranslator.translateType(type))
+    return result;
 
-    return LLVMType::getFunctionTy(result, paramTypes, fty->isVarArg());
-  }
-  default: {
-    // FIXME: Diagnostic should be able to natively handle types that have
-    // operator<<(raw_ostream&) defined.
-    std::string s;
-    llvm::raw_string_ostream os(s);
-    os << *type;
-    emitError(unknownLoc) << "unhandled type: " << os.str();
-    return nullptr;
-  }
-  }
+  // FIXME: Diagnostic should be able to natively handle types that have
+  // operator<<(raw_ostream&) defined.
+  std::string s;
+  llvm::raw_string_ostream os(s);
+  os << *type;
+  emitError(unknownLoc) << "unhandled type: " << os.str();
+  return nullptr;
 }
 
 // We only need integers, floats, doubles, and vectors and tensors thereof for
index 5107efe..9275875 100644 (file)
@@ -304,7 +304,8 @@ ModuleTranslation::ModuleTranslation(Operation *module,
           std::make_unique<DebugTranslation>(module, *this->llvmModule)),
       ompDialect(
           module->getContext()->getRegisteredDialect<omp::OpenMPDialect>()),
-      llvmDialect(module->getContext()->getRegisteredDialect<LLVMDialect>()) {
+      llvmDialect(module->getContext()->getRegisteredDialect<LLVMDialect>()),
+      typeTranslator(this->llvmModule->getContext()) {
   assert(satisfiesLLVMModule(mlirModule) &&
          "mlirModule should honor LLVM's module semantics.");
 }
@@ -935,7 +936,7 @@ LogicalResult ModuleTranslation::convertFunctions() {
 llvm::Type *ModuleTranslation::convertType(LLVMType type) {
   // Lock the LLVM context as we create types in it.
   llvm::sys::SmartScopedLock<true> lock(llvmDialect->getLLVMContextMutex());
-  return LLVM::translateTypeToLLVMIR(type, llvmDialect->getLLVMContext());
+  return typeTranslator.translateType(type);
 }
 
 /// A helper to look up remapped operands in the value remapping table.`
index b327e9e..2a4325f 100644 (file)
 #include "mlir/IR/MLIRContext.h"
 
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
 
 using namespace mlir;
 
-namespace {
+namespace mlir {
+namespace LLVM {
+namespace detail {
 /// Support for translating MLIR LLVM dialect types to LLVM IR.
-class TypeToLLVMIRTranslator {
+class TypeToLLVMIRTranslatorImpl {
 public:
   /// Constructs a class creating types in the given LLVM context.
-  TypeToLLVMIRTranslator(llvm::LLVMContext &context) : context(context) {}
+  TypeToLLVMIRTranslatorImpl(llvm::LLVMContext &context) : context(context) {}
 
   /// Translates a single type.
   llvm::Type *translateType(LLVM::LLVMType type) {
@@ -160,22 +163,32 @@ private:
   /// type instead of creating a new type.
   llvm::DenseMap<LLVM::LLVMType, llvm::Type *> knownTranslations;
 };
-} // end namespace
-
-/// Translates a type from MLIR LLVM dialect to LLVM IR. This does not maintain
-/// the mapping for identified structs so new structs will be created with
-/// auto-renaming on each call. This is intended exclusively for testing.
-llvm::Type *mlir::LLVM::translateTypeToLLVMIR(LLVM::LLVMType type,
-                                              llvm::LLVMContext &context) {
-  return TypeToLLVMIRTranslator(context).translateType(type);
+} // end namespace detail
+} // end namespace LLVM
+} // end namespace mlir
+
+LLVM::TypeToLLVMIRTranslator::TypeToLLVMIRTranslator(llvm::LLVMContext &context)
+    : impl(new detail::TypeToLLVMIRTranslatorImpl(context)) {}
+
+LLVM::TypeToLLVMIRTranslator::~TypeToLLVMIRTranslator() {}
+
+llvm::Type *LLVM::TypeToLLVMIRTranslator::translateType(LLVM::LLVMType type) {
+  return impl->translateType(type);
 }
 
-namespace {
+unsigned LLVM::TypeToLLVMIRTranslator::getPreferredAlignment(
+    LLVM::LLVMType type, const llvm::DataLayout &layout) {
+  return layout.getPrefTypeAlignment(translateType(type));
+}
+
+namespace mlir {
+namespace LLVM {
+namespace detail {
 /// Support for translating LLVM IR types to MLIR LLVM dialect types.
-class TypeFromLLVMIRTranslator {
+class TypeFromLLVMIRTranslatorImpl {
 public:
   /// Constructs a class creating types in the given MLIR context.
-  TypeFromLLVMIRTranslator(MLIRContext &context) : context(context) {}
+  TypeFromLLVMIRTranslatorImpl(MLIRContext &context) : context(context) {}
 
   /// Translates the given type.
   LLVM::LLVMType translateType(llvm::Type *type) {
@@ -299,11 +312,15 @@ private:
   /// The context in which MLIR types are created.
   MLIRContext &context;
 };
-} // end namespace
+} // end namespace detail
+} // end namespace LLVM
+} // end namespace mlir
+
+LLVM::TypeFromLLVMIRTranslator::TypeFromLLVMIRTranslator(MLIRContext &context)
+    : impl(new detail::TypeFromLLVMIRTranslatorImpl(context)) {}
+
+LLVM::TypeFromLLVMIRTranslator::~TypeFromLLVMIRTranslator() {}
 
-/// Translates a type from LLVM IR to MLIR LLVM dialect. This is intended
-/// exclusively for testing.
-LLVM::LLVMType mlir::LLVM::translateTypeFromLLVMIR(llvm::Type *type,
-                                                   MLIRContext &context) {
-  return TypeFromLLVMIRTranslator(context).translateType(type);
+LLVM::LLVMType LLVM::TypeFromLLVMIRTranslator::translateType(llvm::Type *type) {
+  return impl->translateType(type);
 }
index d67bbb0..b3cfad9 100644 (file)
@@ -3,7 +3,7 @@
 %struct.t = type {}
 %struct.s = type { %struct.t, i64 }
 
-; CHECK: llvm.mlir.global external @g1() : !llvm.struct<(struct<()>, i64)>
+; CHECK: llvm.mlir.global external @g1() : !llvm.struct<"struct.s", (struct<"struct.t", ()>, i64)>
 @g1 = external global %struct.s, align 8
 ; CHECK: llvm.mlir.global external @g2() : !llvm.double
 @g2 = external global double, align 8
index a3026e5..77f7800 100644 (file)
-// RUN: mlir-translate -test-mlir-to-llvmir -split-input-file %s | FileCheck %s
-
-llvm.func @primitives() {
-  // CHECK: declare void @return_void()
-  // CHECK: declare void @return_void_round()
-  "llvm.test_introduce_func"() { name = "return_void", type = !llvm.void } : () -> ()
-  // CHECK: declare half @return_half()
-  // CHECK: declare half @return_half_round()
-  "llvm.test_introduce_func"() { name = "return_half", type = !llvm.half } : () -> ()
-  // CHECK: declare bfloat @return_bfloat()
-  // CHECK: declare bfloat @return_bfloat_round()
-  "llvm.test_introduce_func"() { name = "return_bfloat", type = !llvm.bfloat } : () -> ()
-  // CHECK: declare float @return_float()
-  // CHECK: declare float @return_float_round()
-  "llvm.test_introduce_func"() { name = "return_float", type = !llvm.float } : () -> ()
-  // CHECK: declare double @return_double()
-  // CHECK: declare double @return_double_round()
-  "llvm.test_introduce_func"() { name = "return_double", type = !llvm.double } : () -> ()
-  // CHECK: declare fp128 @return_fp128()
-  // CHECK: declare fp128 @return_fp128_round()
-  "llvm.test_introduce_func"() { name = "return_fp128", type = !llvm.fp128 } : () -> ()
-  // CHECK: declare x86_fp80 @return_x86_fp80()
-  // CHECK: declare x86_fp80 @return_x86_fp80_round()
-  "llvm.test_introduce_func"() { name = "return_x86_fp80", type = !llvm.x86_fp80 } : () -> ()
-  // CHECK: declare ppc_fp128 @return_ppc_fp128()
-  // CHECK: declare ppc_fp128 @return_ppc_fp128_round()
-  "llvm.test_introduce_func"() { name = "return_ppc_fp128", type = !llvm.ppc_fp128 } : () -> ()
-  // CHECK: declare x86_mmx @return_x86_mmx()
-  // CHECK: declare x86_mmx @return_x86_mmx_round()
-  "llvm.test_introduce_func"() { name = "return_x86_mmx", type = !llvm.x86_mmx } : () -> ()
-  llvm.return
-}
-
-llvm.func @funcs() {
-  // CHECK: declare void @f_void_i32(i32)
-  // CHECK: declare void @f_void_i32_round(i32)
-  "llvm.test_introduce_func"() { name ="f_void_i32", type = !llvm.func<void (i32)> } : () -> ()
-  // CHECK: declare i32 @f_i32_empty()
-  // CHECK: declare i32 @f_i32_empty_round()
-  "llvm.test_introduce_func"() { name ="f_i32_empty", type = !llvm.func<i32 ()> } : () -> ()
-  // CHECK: declare i32 @f_i32_half_bfloat_float_double(half, bfloat, float, double)
-  // CHECK: declare i32 @f_i32_half_bfloat_float_double_round(half, bfloat, float, double)
-  "llvm.test_introduce_func"() { name ="f_i32_half_bfloat_float_double", type = !llvm.func<i32 (half, bfloat, float, double)> } : () -> ()
-  // CHECK: declare i32 @f_i32_i32_i32(i32, i32)
-  // CHECK: declare i32 @f_i32_i32_i32_round(i32, i32)
-  "llvm.test_introduce_func"() { name ="f_i32_i32_i32", type = !llvm.func<i32 (i32, i32)> } : () -> ()
-  // CHECK: declare void @f_void_variadic(...)
-  // CHECK: declare void @f_void_variadic_round(...)
-  "llvm.test_introduce_func"() { name ="f_void_variadic", type = !llvm.func<void (...)> } : () -> ()
-  // CHECK: declare void @f_void_i32_i32_variadic(i32, i32, ...)
-  // CHECK: declare void @f_void_i32_i32_variadic_round(i32, i32, ...)
-  "llvm.test_introduce_func"() { name ="f_void_i32_i32_variadic", type = !llvm.func<void (i32, i32, ...)> } : () -> ()
-  llvm.return
-}
-
-llvm.func @ints() {
-  // CHECK: declare i1 @return_i1()
-  // CHECK: declare i1 @return_i1_round()
-  "llvm.test_introduce_func"() { name = "return_i1", type = !llvm.i1 } : () -> ()
-  // CHECK: declare i8 @return_i8()
-  // CHECK: declare i8 @return_i8_round()
-  "llvm.test_introduce_func"() { name = "return_i8", type = !llvm.i8 } : () -> ()
-  // CHECK: declare i16 @return_i16()
-  // CHECK: declare i16 @return_i16_round()
-  "llvm.test_introduce_func"() { name = "return_i16", type = !llvm.i16 } : () -> ()
-  // CHECK: declare i32 @return_i32()
-  // CHECK: declare i32 @return_i32_round()
-  "llvm.test_introduce_func"() { name = "return_i32", type = !llvm.i32 } : () -> ()
-  // CHECK: declare i64 @return_i64()
-  // CHECK: declare i64 @return_i64_round()
-  "llvm.test_introduce_func"() { name = "return_i64", type = !llvm.i64 } : () -> ()
-  // CHECK: declare i57 @return_i57()
-  // CHECK: declare i57 @return_i57_round()
-  "llvm.test_introduce_func"() { name = "return_i57", type = !llvm.i57 } : () -> ()
-  // CHECK: declare i129 @return_i129()
-  // CHECK: declare i129 @return_i129_round()
-  "llvm.test_introduce_func"() { name = "return_i129", type = !llvm.i129 } : () -> ()
-  llvm.return
-}
-
-llvm.func @pointers() {
-  // CHECK: declare i8* @return_pi8()
-  // CHECK: declare i8* @return_pi8_round()
-  "llvm.test_introduce_func"() { name = "return_pi8", type = !llvm.ptr<i8> } : () -> ()
-  // CHECK: declare float* @return_pfloat()
-  // CHECK: declare float* @return_pfloat_round()
-  "llvm.test_introduce_func"() { name = "return_pfloat", type = !llvm.ptr<float> } : () -> ()
-  // CHECK: declare i8** @return_ppi8()
-  // CHECK: declare i8** @return_ppi8_round()
-  "llvm.test_introduce_func"() { name = "return_ppi8", type = !llvm.ptr<ptr<i8>> } : () -> ()
-  // CHECK: declare i8***** @return_pppppi8()
-  // CHECK: declare i8***** @return_pppppi8_round()
-  "llvm.test_introduce_func"() { name = "return_pppppi8", type = !llvm.ptr<ptr<ptr<ptr<ptr<i8>>>>> } : () -> ()
-  // CHECK: declare i8* @return_pi8_0()
-  // CHECK: declare i8* @return_pi8_0_round()
-  "llvm.test_introduce_func"() { name = "return_pi8_0", type = !llvm.ptr<i8, 0> } : () -> ()
-  // CHECK: declare i8 addrspace(1)* @return_pi8_1()
-  // CHECK: declare i8 addrspace(1)* @return_pi8_1_round()
-  "llvm.test_introduce_func"() { name = "return_pi8_1", type = !llvm.ptr<i8, 1> } : () -> ()
-  // CHECK: declare i8 addrspace(42)* @return_pi8_42()
-  // CHECK: declare i8 addrspace(42)* @return_pi8_42_round()
-  "llvm.test_introduce_func"() { name = "return_pi8_42", type = !llvm.ptr<i8, 42> } : () -> ()
-  // CHECK: declare i8 addrspace(42)* addrspace(9)* @return_ppi8_42_9()
-  // CHECK: declare i8 addrspace(42)* addrspace(9)* @return_ppi8_42_9_round()
-  "llvm.test_introduce_func"() { name = "return_ppi8_42_9", type = !llvm.ptr<ptr<i8, 42>, 9> } : () -> ()
-  llvm.return
-}
-
-llvm.func @vectors() {
-  // CHECK: declare <4 x i32> @return_v4_i32()
-  // CHECK: declare <4 x i32> @return_v4_i32_round()
-  "llvm.test_introduce_func"() { name = "return_v4_i32", type = !llvm.vec<4 x i32> } : () -> ()
-  // CHECK: declare <4 x float> @return_v4_float()
-  // CHECK: declare <4 x float> @return_v4_float_round()
-  "llvm.test_introduce_func"() { name = "return_v4_float", type = !llvm.vec<4 x float> } : () -> ()
-  // CHECK: declare <vscale x 4 x i32> @return_vs_4_i32()
-  // CHECK: declare <vscale x 4 x i32> @return_vs_4_i32_round()
-  "llvm.test_introduce_func"() { name = "return_vs_4_i32", type = !llvm.vec<? x 4 x i32> } : () -> ()
-  // CHECK: declare <vscale x 8 x half> @return_vs_8_half()
-  // CHECK: declare <vscale x 8 x half> @return_vs_8_half_round()
-  "llvm.test_introduce_func"() { name = "return_vs_8_half", type = !llvm.vec<? x 8 x half> } : () -> ()
-  // CHECK: declare <4 x i8*> @return_v_4_pi8()
-  // CHECK: declare <4 x i8*> @return_v_4_pi8_round()
-  "llvm.test_introduce_func"() { name = "return_v_4_pi8", type = !llvm.vec<4 x ptr<i8>> } : () -> ()
-  llvm.return
-}
-
-llvm.func @arrays() {
-  // CHECK: declare [10 x i32] @return_a10_i32()
-  // CHECK: declare [10 x i32] @return_a10_i32_round()
-  "llvm.test_introduce_func"() { name = "return_a10_i32", type = !llvm.array<10 x i32> } : () -> ()
-  // CHECK: declare [8 x float] @return_a8_float()
-  // CHECK: declare [8 x float] @return_a8_float_round()
-  "llvm.test_introduce_func"() { name = "return_a8_float", type = !llvm.array<8 x float> } : () -> ()
-  // CHECK: declare [10 x i32 addrspace(4)*] @return_a10_pi32_4()
-  // CHECK: declare [10 x i32 addrspace(4)*] @return_a10_pi32_4_round()
-  "llvm.test_introduce_func"() { name = "return_a10_pi32_4", type = !llvm.array<10 x ptr<i32, 4>> } : () -> ()
-  // CHECK: declare [10 x [4 x float]] @return_a10_a4_float()
-  // CHECK: declare [10 x [4 x float]] @return_a10_a4_float_round()
-  "llvm.test_introduce_func"() { name = "return_a10_a4_float", type = !llvm.array<10 x array<4 x float>> } : () -> ()
-  llvm.return
-}
-
-llvm.func @literal_structs() {
-  // CHECK: declare {} @return_struct_empty()
-  // CHECK: declare {} @return_struct_empty_round()
-  "llvm.test_introduce_func"() { name = "return_struct_empty", type = !llvm.struct<()> } : () -> ()
-  // CHECK: declare { i32 } @return_s_i32()
-  // CHECK: declare { i32 } @return_s_i32_round()
-  "llvm.test_introduce_func"() { name = "return_s_i32", type = !llvm.struct<(i32)> } : () -> ()
-  // CHECK: declare { float, i32 } @return_s_float_i32()
-  // CHECK: declare { float, i32 } @return_s_float_i32_round()
-  "llvm.test_introduce_func"() { name = "return_s_float_i32", type = !llvm.struct<(float, i32)> } : () -> ()
-  // CHECK: declare { { i32 } } @return_s_s_i32()
-  // CHECK: declare { { i32 } } @return_s_s_i32_round()
-  "llvm.test_introduce_func"() { name = "return_s_s_i32", type = !llvm.struct<(struct<(i32)>)> } : () -> ()
-  // CHECK: declare { i32, { i32 }, float } @return_s_i32_s_i32_float()
-  // CHECK: declare { i32, { i32 }, float } @return_s_i32_s_i32_float_round()
-  "llvm.test_introduce_func"() { name = "return_s_i32_s_i32_float", type = !llvm.struct<(i32, struct<(i32)>, float)> } : () -> ()
-
-  // CHECK: declare <{}> @return_sp_empty()
-  // CHECK: declare <{}> @return_sp_empty_round()
-  "llvm.test_introduce_func"() { name = "return_sp_empty", type = !llvm.struct<packed ()> } : () -> ()
-  // CHECK: declare <{ i32 }> @return_sp_i32()
-  // CHECK: declare <{ i32 }> @return_sp_i32_round()
-  "llvm.test_introduce_func"() { name = "return_sp_i32", type = !llvm.struct<packed (i32)> } : () -> ()
-  // CHECK: declare <{ float, i32 }> @return_sp_float_i32()
-  // CHECK: declare <{ float, i32 }> @return_sp_float_i32_round()
-  "llvm.test_introduce_func"() { name = "return_sp_float_i32", type = !llvm.struct<packed (float, i32)> } : () -> ()
-  // CHECK: declare <{ i32, { i32, i1 }, float }> @return_sp_i32_s_i31_1_float()
-  // CHECK: declare <{ i32, { i32, i1 }, float }> @return_sp_i32_s_i31_1_float_round()
-  "llvm.test_introduce_func"() { name = "return_sp_i32_s_i31_1_float", type = !llvm.struct<packed (i32, struct<(i32, i1)>, float)> } : () -> ()
-
-  // CHECK: declare { <{ i32 }> } @return_s_sp_i32()
-  // CHECK: declare { <{ i32 }> } @return_s_sp_i32_round()
-  "llvm.test_introduce_func"() { name = "return_s_sp_i32", type = !llvm.struct<(struct<packed (i32)>)> } : () -> ()
-  // CHECK: declare <{ { i32 } }> @return_sp_s_i32()
-  // CHECK: declare <{ { i32 } }> @return_sp_s_i32_round()
-  "llvm.test_introduce_func"() { name = "return_sp_s_i32", type = !llvm.struct<packed (struct<(i32)>)> } : () -> ()
-  llvm.return
-}
+// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
+
+//
+// Primitives.
+//
+
+// CHECK: declare void @return_void()
+llvm.func @return_void() -> !llvm.void
+// CHECK: declare half @return_half()
+llvm.func @return_half() -> !llvm.half
+// CHECK: declare bfloat @return_bfloat()
+llvm.func @return_bfloat() -> !llvm.bfloat
+// CHECK: declare float @return_float()
+llvm.func @return_float() -> !llvm.float
+// CHECK: declare double @return_double()
+llvm.func @return_double() -> !llvm.double
+// CHECK: declare fp128 @return_fp128()
+llvm.func @return_fp128() -> !llvm.fp128
+// CHECK: declare x86_fp80 @return_x86_fp80()
+llvm.func @return_x86_fp80() -> !llvm.x86_fp80
+// CHECK: declare ppc_fp128 @return_ppc_fp128()
+llvm.func @return_ppc_fp128() -> !llvm.ppc_fp128
+// CHECK: declare x86_mmx @return_x86_mmx()
+llvm.func @return_x86_mmx() -> !llvm.x86_mmx
+
+//
+// Functions.
+//
+
+// CHECK: declare void @f_void_i32(i32)
+llvm.func @f_void_i32(!llvm.i32) -> !llvm.void
+// CHECK: declare i32 @f_i32_empty()
+llvm.func @f_i32_empty() -> !llvm.i32
+// CHECK: declare i32 @f_i32_half_bfloat_float_double(half, bfloat, float, double)
+llvm.func @f_i32_half_bfloat_float_double(!llvm.half, !llvm.bfloat, !llvm.float, !llvm.double) -> !llvm.i32
+// CHECK: declare i32 @f_i32_i32_i32(i32, i32)
+llvm.func @f_i32_i32_i32(!llvm.i32, !llvm.i32) -> !llvm.i32
+// CHECK: declare void @f_void_variadic(...)
+llvm.func @f_void_variadic(...)
+// CHECK: declare void @f_void_i32_i32_variadic(i32, i32, ...)
+llvm.func @f_void_i32_i32_variadic(!llvm.i32, !llvm.i32, ...)
+// CHECK: declare i32 (i32)* @f_f_i32_i32()
+llvm.func @f_f_i32_i32() -> !llvm.ptr<func<i32 (i32)>>
+
+//
+// Integers.
+//
+
+// CHECK: declare i1 @return_i1()
+llvm.func @return_i1() -> !llvm.i1
+// CHECK: declare i8 @return_i8()
+llvm.func @return_i8() -> !llvm.i8
+// CHECK: declare i16 @return_i16()
+llvm.func @return_i16() -> !llvm.i16
+// CHECK: declare i32 @return_i32()
+llvm.func @return_i32() -> !llvm.i32
+// CHECK: declare i64 @return_i64()
+llvm.func @return_i64() -> !llvm.i64
+// CHECK: declare i57 @return_i57()
+llvm.func @return_i57() -> !llvm.i57
+// CHECK: declare i129 @return_i129()
+llvm.func @return_i129() -> !llvm.i129
+
+//
+// Pointers.
+//
+
+// CHECK: declare i8* @return_pi8()
+llvm.func @return_pi8() -> !llvm.ptr<i8>
+// CHECK: declare float* @return_pfloat()
+llvm.func @return_pfloat() -> !llvm.ptr<float>
+// CHECK: declare i8** @return_ppi8()
+llvm.func @return_ppi8() -> !llvm.ptr<ptr<i8>>
+// CHECK: declare i8***** @return_pppppi8()
+llvm.func @return_pppppi8() -> !llvm.ptr<ptr<ptr<ptr<ptr<i8>>>>>
+// CHECK: declare i8* @return_pi8_0()
+llvm.func @return_pi8_0() -> !llvm.ptr<i8, 0>
+// CHECK: declare i8 addrspace(1)* @return_pi8_1()
+llvm.func @return_pi8_1() -> !llvm.ptr<i8, 1>
+// CHECK: declare i8 addrspace(42)* @return_pi8_42()
+llvm.func @return_pi8_42() -> !llvm.ptr<i8, 42>
+// CHECK: declare i8 addrspace(42)* addrspace(9)* @return_ppi8_42_9()
+llvm.func @return_ppi8_42_9() -> !llvm.ptr<ptr<i8, 42>, 9>
+
+//
+// Vectors.
+//
+
+// CHECK: declare <4 x i32> @return_v4_i32()
+llvm.func @return_v4_i32() -> !llvm.vec<4 x i32>
+// CHECK: declare <4 x float> @return_v4_float()
+llvm.func @return_v4_float() -> !llvm.vec<4 x float>
+// CHECK: declare <vscale x 4 x i32> @return_vs_4_i32()
+llvm.func @return_vs_4_i32() -> !llvm.vec<? x 4 x i32>
+// CHECK: declare <vscale x 8 x half> @return_vs_8_half()
+llvm.func @return_vs_8_half() -> !llvm.vec<? x 8 x half>
+// CHECK: declare <4 x i8*> @return_v_4_pi8()
+llvm.func @return_v_4_pi8() -> !llvm.vec<4 x ptr<i8>>
+
+//
+// Arrays.
+//
+
+// CHECK: declare [10 x i32] @return_a10_i32()
+llvm.func @return_a10_i32() -> !llvm.array<10 x i32>
+// CHECK: declare [8 x float] @return_a8_float()
+llvm.func @return_a8_float() -> !llvm.array<8 x float>
+// CHECK: declare [10 x i32 addrspace(4)*] @return_a10_pi32_4()
+llvm.func @return_a10_pi32_4() -> !llvm.array<10 x ptr<i32, 4>>
+// CHECK: declare [10 x [4 x float]] @return_a10_a4_float()
+llvm.func @return_a10_a4_float() -> !llvm.array<10 x array<4 x float>>
+
+//
+// Literal structures.
+//
+
+// CHECK: declare {} @return_struct_empty()
+llvm.func @return_struct_empty() -> !llvm.struct<()>
+// CHECK: declare { i32 } @return_s_i32()
+llvm.func @return_s_i32() -> !llvm.struct<(i32)>
+// CHECK: declare { float, i32 } @return_s_float_i32()
+llvm.func @return_s_float_i32() -> !llvm.struct<(float, i32)>
+// CHECK: declare { { i32 } } @return_s_s_i32()
+llvm.func @return_s_s_i32() -> !llvm.struct<(struct<(i32)>)>
+// CHECK: declare { i32, { i32 }, float } @return_s_i32_s_i32_float()
+llvm.func @return_s_i32_s_i32_float() -> !llvm.struct<(i32, struct<(i32)>, float)>
+
+// CHECK: declare <{}> @return_sp_empty()
+llvm.func @return_sp_empty() -> !llvm.struct<packed ()>
+// CHECK: declare <{ i32 }> @return_sp_i32()
+llvm.func @return_sp_i32() -> !llvm.struct<packed (i32)>
+// CHECK: declare <{ float, i32 }> @return_sp_float_i32()
+llvm.func @return_sp_float_i32() -> !llvm.struct<packed (float, i32)>
+// CHECK: declare <{ i32, { i32, i1 }, float }> @return_sp_i32_s_i31_1_float()
+llvm.func @return_sp_i32_s_i31_1_float() -> !llvm.struct<packed (i32, struct<(i32, i1)>, float)>
+
+// CHECK: declare { <{ i32 }> } @return_s_sp_i32()
+llvm.func @return_s_sp_i32() -> !llvm.struct<(struct<packed (i32)>)>
+// CHECK: declare <{ { i32 } }> @return_sp_s_i32()
+llvm.func @return_sp_s_i32() -> !llvm.struct<packed (struct<(i32)>)>
 
 // -----
 // Put structs into a separate split so that we can match their declarations
@@ -197,32 +156,29 @@ llvm.func @literal_structs() {
 // CHECK: %array-of-structs = type { i32 }
 // CHECK: %ptr-to-struct = type { i8 }
 
-llvm.func @identified_structs() {
-  // CHECK: declare %empty
-  "llvm.test_introduce_func"() { name = "return_s_empty", type = !llvm.struct<"empty", ()> } : () -> ()
-  // CHECK: declare %opaque
-  "llvm.test_introduce_func"() { name = "return_s_opaque", type = !llvm.struct<"opaque", opaque> } : () -> ()
-  // CHECK: declare %long
-  "llvm.test_introduce_func"() { name = "return_s_long", type = !llvm.struct<"long", (i32, struct<(i32, i1)>, float, ptr<func<void ()>>)> } : () -> ()
-  // CHECK: declare %self-recursive
-  "llvm.test_introduce_func"() { name = "return_s_self_recurisve", type = !llvm.struct<"self-recursive", (ptr<struct<"self-recursive">>)> } : () -> ()
-  // CHECK: declare %unpacked
-  "llvm.test_introduce_func"() { name = "return_s_unpacked", type = !llvm.struct<"unpacked", (i32)> } : () -> ()
-  // CHECK: declare %packed
-  "llvm.test_introduce_func"() { name = "return_s_packed", type = !llvm.struct<"packed", packed (i32)> } : () -> ()
-  // CHECK: declare %"name with spaces and !^$@$#"
-  "llvm.test_introduce_func"() { name = "return_s_symbols", type = !llvm.struct<"name with spaces and !^$@$#", packed (i32)> } : () -> ()
-
-  // CHECK: declare %mutually-a
-  "llvm.test_introduce_func"() { name = "return_s_mutually_a", type = !llvm.struct<"mutually-a", (ptr<struct<"mutually-b", (ptr<struct<"mutually-a">, 3>)>>)> } : () -> ()
-  // CHECK: declare %mutually-b
-  "llvm.test_introduce_func"() { name = "return_s_mutually_b", type = !llvm.struct<"mutually-b", (ptr<struct<"mutually-a", (ptr<struct<"mutually-b">>)>, 3>)> } : () -> ()
-
-  // CHECK: declare %struct-of-arrays
-  "llvm.test_introduce_func"() { name = "return_s_struct_of_arrays", type = !llvm.struct<"struct-of-arrays", (array<10 x i32>)> } : () -> ()
-  // CHECK: declare [10 x %array-of-structs]
-  "llvm.test_introduce_func"() { name = "return_s_array_of_structs", type = !llvm.array<10 x struct<"array-of-structs", (i32)>> } : () -> ()
-  // CHECK: declare %ptr-to-struct*
-  "llvm.test_introduce_func"() { name = "return_s_ptr_to_struct", type = !llvm.ptr<struct<"ptr-to-struct", (i8)>> } : () -> ()
-  llvm.return
-}
+// CHECK: declare %empty
+llvm.func @return_s_empty() -> !llvm.struct<"empty", ()>
+// CHECK: declare %opaque
+llvm.func @return_s_opaque() -> !llvm.struct<"opaque", opaque>
+// CHECK: declare %long
+llvm.func @return_s_long() -> !llvm.struct<"long", (i32, struct<(i32, i1)>, float, ptr<func<void ()>>)>
+// CHECK: declare %self-recursive
+llvm.func @return_s_self_recurisve() -> !llvm.struct<"self-recursive", (ptr<struct<"self-recursive">>)>
+// CHECK: declare %unpacked
+llvm.func @return_s_unpacked() -> !llvm.struct<"unpacked", (i32)>
+// CHECK: declare %packed
+llvm.func @return_s_packed() -> !llvm.struct<"packed", packed (i32)>
+// CHECK: declare %"name with spaces and !^$@$#"
+llvm.func @return_s_symbols() -> !llvm.struct<"name with spaces and !^$@$#", packed (i32)>
+
+// CHECK: declare %mutually-a
+llvm.func @return_s_mutually_a() -> !llvm.struct<"mutually-a", (ptr<struct<"mutually-b", (ptr<struct<"mutually-a">, 3>)>>)>
+// CHECK: declare %mutually-b
+llvm.func @return_s_mutually_b() -> !llvm.struct<"mutually-b", (ptr<struct<"mutually-a", (ptr<struct<"mutually-b">>)>, 3>)>
+
+// CHECK: declare %struct-of-arrays
+llvm.func @return_s_struct_of_arrays() -> !llvm.struct<"struct-of-arrays", (array<10 x i32>)>
+// CHECK: declare [10 x %array-of-structs]
+llvm.func @return_s_array_of_structs() -> !llvm.array<10 x struct<"array-of-structs", (i32)>>
+// CHECK: declare %ptr-to-struct*
+llvm.func @return_s_ptr_to_struct() -> !llvm.ptr<struct<"ptr-to-struct", (i8)>>
index ec9e5cd..0df357c 100644 (file)
@@ -2,5 +2,4 @@ add_subdirectory(Dialect)
 add_subdirectory(IR)
 add_subdirectory(Pass)
 add_subdirectory(Reducer)
-add_subdirectory(Target)
 add_subdirectory(Transforms)
diff --git a/mlir/test/lib/Target/CMakeLists.txt b/mlir/test/lib/Target/CMakeLists.txt
deleted file mode 100644 (file)
index cb8f206..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-add_mlir_translation_library(MLIRTestLLVMTypeTranslation
-  TestLLVMTypeTranslation.cpp
-
-  LINK_COMPONENTS
-  Core
-  TransformUtils
-
-  LINK_LIBS PUBLIC
-  MLIRLLVMIR
-  MLIRTargetLLVMIRModuleTranslation
-  MLIRTestIR
-  MLIRTranslation
-  )
diff --git a/mlir/test/lib/Target/TestLLVMTypeTranslation.cpp b/mlir/test/lib/Target/TestLLVMTypeTranslation.cpp
deleted file mode 100644 (file)
index e517343..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-//===- TestLLVMTypeTranslation.cpp - Test MLIR/LLVM IR type translation ---===//
-//
-// 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 "mlir/Dialect/LLVMIR/LLVMTypes.h"
-#include "mlir/Target/LLVMIR/ModuleTranslation.h"
-#include "mlir/Target/LLVMIR/TypeTranslation.h"
-#include "mlir/Translation.h"
-
-using namespace mlir;
-
-namespace {
-class TestLLVMTypeTranslation : public LLVM::ModuleTranslation {
-  // Allow access to the constructors under MSVC.
-  friend LLVM::ModuleTranslation;
-
-public:
-  using LLVM::ModuleTranslation::ModuleTranslation;
-
-protected:
-  /// Simple test facility for translating types from MLIR LLVM dialect to LLVM
-  /// IR. This converts the "llvm.test_introduce_func" operation into an LLVM IR
-  /// function with the name extracted from the `name` attribute that returns
-  /// the type contained in the `type` attribute if it is a non-function type or
-  /// that has the signature obtained by converting `type` if it is a function
-  /// type. This is a temporary check before type translation is substituted
-  /// into the main translation flow and exercised here.
-  LogicalResult convertOperation(Operation &op,
-                                 llvm::IRBuilder<> &builder) override {
-    if (op.getName().getStringRef() == "llvm.test_introduce_func") {
-      auto attr = op.getAttrOfType<TypeAttr>("type");
-      assert(attr && "expected 'type' attribute");
-      auto type = attr.getValue().cast<LLVM::LLVMType>();
-
-      auto nameAttr = op.getAttrOfType<StringAttr>("name");
-      assert(nameAttr && "expected 'name' attributes");
-
-      llvm::Type *translated =
-          LLVM::translateTypeToLLVMIR(type, builder.getContext());
-
-      llvm::Module *module = builder.GetInsertBlock()->getModule();
-      if (auto *funcType = dyn_cast<llvm::FunctionType>(translated))
-        module->getOrInsertFunction(nameAttr.getValue(), funcType);
-      else
-        module->getOrInsertFunction(nameAttr.getValue(), translated);
-
-      std::string roundtripName = (Twine(nameAttr.getValue()) + "_round").str();
-      LLVM::LLVMType translatedBack =
-          LLVM::translateTypeFromLLVMIR(translated, *op.getContext());
-      llvm::Type *translatedBackAndForth =
-          LLVM::translateTypeToLLVMIR(translatedBack, builder.getContext());
-      if (auto *funcType = dyn_cast<llvm::FunctionType>(translatedBackAndForth))
-        module->getOrInsertFunction(roundtripName, funcType);
-      else
-        module->getOrInsertFunction(roundtripName, translatedBackAndForth);
-      return success();
-    }
-
-    return LLVM::ModuleTranslation::convertOperation(op, builder);
-  }
-};
-} // namespace
-
-namespace mlir {
-void registerTestLLVMTypeTranslation() {
-  TranslateFromMLIRRegistration reg(
-      "test-mlir-to-llvmir", [](ModuleOp module, raw_ostream &output) {
-        std::unique_ptr<llvm::Module> llvmModule =
-            LLVM::ModuleTranslation::translateModule<TestLLVMTypeTranslation>(
-                module.getOperation());
-        llvmModule->print(output, nullptr);
-        return success();
-      });
-}
-} // namespace mlir
index 1f2ddca..914bd34 100644 (file)
@@ -49,13 +49,11 @@ static llvm::cl::opt<bool> verifyDiagnostics(
 
 namespace mlir {
 // Defined in the test directory, no public header.
-void registerTestLLVMTypeTranslation();
 void registerTestRoundtripSPIRV();
 void registerTestRoundtripDebugSPIRV();
 } // namespace mlir
 
 static void registerTestTranslations() {
-  registerTestLLVMTypeTranslation();
   registerTestRoundtripSPIRV();
   registerTestRoundtripDebugSPIRV();
 }