[MLIR][SPIRVToLLVM] Add skeleton for SPIR-V to LLVM dialect conversion
authorGeorge Mitenkov <georgemitenk0v@gmail.com>
Mon, 8 Jun 2020 22:20:52 +0000 (18:20 -0400)
committerLei Zhang <antiagainst@google.com>
Mon, 8 Jun 2020 22:22:42 +0000 (18:22 -0400)
These commits set up the skeleton for SPIR-V to LLVM dialect conversion.
I created SPIR-V to LLVM pass, registered it in Passes.td, InitAllPasses.h.
Added a pattern for `spv.BitwiseAndOp` and tests for it. Integer, float
and vector types are converted through LLVMTypeConverter.

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

mlir/include/mlir/Conversion/Passes.td
mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h [new file with mode: 0644]
mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.h [new file with mode: 0644]
mlir/include/mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h
mlir/include/mlir/InitAllPasses.h
mlir/lib/Conversion/CMakeLists.txt
mlir/lib/Conversion/SPIRVToLLVM/CMakeLists.txt [new file with mode: 0644]
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp [new file with mode: 0644]
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp [new file with mode: 0644]
mlir/test/Conversion/SPIRVToLLVM/convert-to-llvm.mlir [new file with mode: 0644]

index 4bcfd8d..9b9caa4 100644 (file)
@@ -207,6 +207,15 @@ def ConvertShapeToStandard : Pass<"convert-shape-to-std", "ModuleOp"> {
 }
 
 //===----------------------------------------------------------------------===//
+// SPIRVToLLVM
+//===----------------------------------------------------------------------===//
+
+def ConvertSPIRVToLLVM : Pass<"convert-spirv-to-llvm", "ModuleOp"> {
+  let summary = "Convert SPIR-V dialect to LLVM dialect";
+  let constructor = "mlir::createConvertSPIRVToLLVMPass()";
+}
+
+//===----------------------------------------------------------------------===//
 // StandardToLLVM
 //===----------------------------------------------------------------------===//
 
diff --git a/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h b/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h
new file mode 100644 (file)
index 0000000..2bf74d6
--- /dev/null
@@ -0,0 +1,30 @@
+//===- ConvertSPIRVToLLVM.h - Convert SPIR-V to LLVM dialect ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides patterns to convert SPIR-V dialect to LLVM dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVM_H
+#define MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVM_H
+
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+class LLVMTypeConverter;
+class MLIRContext;
+class ModuleOp;
+
+/// Populates the given list with patterns that convert from SPIR-V to LLVM.
+void populateSPIRVToLLVMConversionPatterns(MLIRContext *context,
+                                           LLVMTypeConverter &typeConverter,
+                                           OwningRewritePatternList &patterns);
+
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVM_H
diff --git a/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.h b/mlir/include/mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.h
new file mode 100644 (file)
index 0000000..9cfce92
--- /dev/null
@@ -0,0 +1,28 @@
+//===- ConvertSPIRVToLLVMPass.h - SPIR-V dialect to LLVM pass ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides a pass to lower from SPIR-V dialect to LLVM dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVMPASS_H
+#define MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVMPASS_H
+
+#include <memory>
+
+namespace mlir {
+class ModuleOp;
+template <typename T>
+class OperationPass;
+
+/// Creates a pass to convert SPIR-V operations to the LLVMIR dialect.
+std::unique_ptr<OperationPass<ModuleOp>> createConvertSPIRVToLLVMPass();
+
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_SPIRVTOLLVM_CONVERTSPIRVTOLLVMPASS_H_
index 0ef6df5..e09a74d 100644 (file)
@@ -13,7 +13,8 @@
 namespace mlir {
 class LLVMTypeConverter;
 class ModuleOp;
-template <typename T> class OperationPass;
+template <typename T>
+class OperationPass;
 
 /// Collect a set of patterns to convert from Vector contractions to LLVM Matrix
 /// Intrinsics. To lower to assembly, the LLVM flag -lower-matrix-intrinsics
index 9571537..f1b78f9 100644 (file)
@@ -25,6 +25,7 @@
 #include "mlir/Conversion/LinalgToStandard/LinalgToStandard.h"
 #include "mlir/Conversion/SCFToGPU/SCFToGPUPass.h"
 #include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
+#include "mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.h"
 #include "mlir/Conversion/ShapeToStandard/ShapeToStandard.h"
 #include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
 #include "mlir/Conversion/StandardToSPIRV/ConvertStandardToSPIRVPass.h"
index c99dcee..e60a1df 100644 (file)
@@ -11,6 +11,7 @@ add_subdirectory(LinalgToStandard)
 add_subdirectory(SCFToGPU)
 add_subdirectory(SCFToStandard)
 add_subdirectory(ShapeToStandard)
+add_subdirectory(SPIRVToLLVM)
 add_subdirectory(StandardToLLVM)
 add_subdirectory(StandardToSPIRV)
 add_subdirectory(VectorToLLVM)
diff --git a/mlir/lib/Conversion/SPIRVToLLVM/CMakeLists.txt b/mlir/lib/Conversion/SPIRVToLLVM/CMakeLists.txt
new file mode 100644 (file)
index 0000000..adf835c
--- /dev/null
@@ -0,0 +1,18 @@
+add_mlir_conversion_library(MLIRSPIRVToLLVM
+  ConvertSPIRVToLLVM.cpp
+  ConvertSPIRVToLLVMPass.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/SPIRVToLLVM
+
+  DEPENDS
+  MLIRConversionPassIncGen
+  intrinsics_gen
+
+  LINK_LIBS PUBLIC
+  MLIRSPIRV
+  MLIRLLVMIR
+  MLIRStandardToLLVM
+  MLIRIR
+  MLIRTransforms
+  )
diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
new file mode 100644 (file)
index 0000000..2ccd243
--- /dev/null
@@ -0,0 +1,53 @@
+//===- ConvertSPIRVToLLVM.cpp - SPIR-V dialect to LLVM dialect conversion -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements patterns to convert SPIR-V dialect to LLVM dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h"
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
+#include "mlir/Dialect/SPIRV/SPIRVOps.h"
+#include "mlir/Dialect/StandardOps/IR/Ops.h"
+#include "mlir/IR/Module.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+using namespace mlir;
+
+namespace {
+
+class BitwiseAndOpConversion : public ConvertToLLVMPattern {
+public:
+  explicit BitwiseAndOpConversion(MLIRContext *context,
+                                  LLVMTypeConverter &typeConverter)
+      : ConvertToLLVMPattern(spirv::BitwiseAndOp::getOperationName(), context,
+                             typeConverter) {}
+
+  LogicalResult
+  matchAndRewrite(Operation *op, ArrayRef<Value> operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto bitwiseAndOp = cast<spirv::BitwiseAndOp>(op);
+    auto dstType = typeConverter.convertType(bitwiseAndOp.getType());
+    if (!dstType)
+      return failure();
+    rewriter.replaceOpWithNewOp<LLVM::AndOp>(bitwiseAndOp, dstType, operands);
+    return success();
+  }
+};
+} // namespace
+
+void mlir::populateSPIRVToLLVMConversionPatterns(
+    MLIRContext *context, LLVMTypeConverter &typeConverter,
+    OwningRewritePatternList &patterns) {
+  patterns.insert<BitwiseAndOpConversion>(context, typeConverter);
+}
diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.cpp
new file mode 100644 (file)
index 0000000..c8e2d73
--- /dev/null
@@ -0,0 +1,54 @@
+//===- ConvertSPIRVToLLVMPass.cpp - Convert SPIR-V ops to LLVM ops --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a pass to convert MLIR SPIR-V ops into LLVM ops
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVMPass.h"
+#include "../PassDetail.h"
+#include "mlir/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.h"
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
+#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/SPIRV/SPIRVDialect.h"
+
+using namespace mlir;
+
+namespace {
+/// A pass converting MLIR SPIR-V operations into LLVM dialect.
+class ConvertSPIRVToLLVMPass
+    : public ConvertSPIRVToLLVMBase<ConvertSPIRVToLLVMPass> {
+  void runOnOperation() override;
+};
+} // namespace
+
+void ConvertSPIRVToLLVMPass::runOnOperation() {
+  MLIRContext *context = &getContext();
+  ModuleOp module = getOperation();
+  LLVMTypeConverter converter(&getContext());
+
+  OwningRewritePatternList patterns;
+  populateSPIRVToLLVMConversionPatterns(context, converter, patterns);
+
+  // Currently pulls in Std to LLVM conversion patterns
+  // that help with testing. This allows to convert
+  // function arguments to LLVM.
+  populateStdToLLVMConversionPatterns(converter, patterns);
+
+  ConversionTarget target(getContext());
+  target.addIllegalDialect<spirv::SPIRVDialect>();
+  target.addLegalDialect<LLVM::LLVMDialect>();
+
+  if (failed(applyPartialConversion(module, target, patterns, &converter)))
+    signalPassFailure();
+}
+
+std::unique_ptr<OperationPass<ModuleOp>> mlir::createConvertSPIRVToLLVMPass() {
+  return std::make_unique<ConvertSPIRVToLLVMPass>();
+}
diff --git a/mlir/test/Conversion/SPIRVToLLVM/convert-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/convert-to-llvm.mlir
new file mode 100644 (file)
index 0000000..326ef3a
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: mlir-opt -convert-spirv-to-llvm %s | FileCheck %s
+
+func @bitwise_and_scalar(%arg0: i32, %arg1: i32) {
+       // CHECK: %{{.*}} = llvm.and %{{.*}}, %{{.*}} : !llvm.i32
+       %0 = spv.BitwiseAnd %arg0, %arg1 : i32
+       return
+}
+
+func @bitwise_and_vector(%arg0: vector<4xi64>, %arg1: vector<4xi64>) {
+       // CHECK: %{{.*}} = llvm.and %{{.*}}, %{{.*}} : !llvm<"<4 x i64>">
+       %0 = spv.BitwiseAnd %arg0, %arg1 : vector<4xi64>
+       return
+}