[Mlir-commits] [mlir] 2ad7e1a - [MLIR][SPIRVToLLVM] Conversion for global and addressof

George Mitenkov llvmlistbot at llvm.org
Tue Aug 11 23:45:23 PDT 2020


Author: George Mitenkov
Date: 2020-08-12T09:41:14+03:00
New Revision: 2ad7e1a301f8af7412208da3ed8049ae08b0fae8

URL: https://github.com/llvm/llvm-project/commit/2ad7e1a301f8af7412208da3ed8049ae08b0fae8
DIFF: https://github.com/llvm/llvm-project/commit/2ad7e1a301f8af7412208da3ed8049ae08b0fae8.diff

LOG: [MLIR][SPIRVToLLVM] Conversion for global and addressof

Inital conversion of `spv._address_of` and `spv.globalVariable`.
In SPIR-V, the global returns a pointer, whereas in LLVM dialect
the global holds an actual value. This difference is handled by
`spv._address_of` and `llvm.mlir.addressof`ops that both return
a pointer. Moreover, only current invocation is in conversion's
scope.

Reviewed By: antiagainst, mravishankar

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

Added: 
    

Modified: 
    mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
    mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
index 024f2b14a9890..e7c5b3c9f6dcd 100644
--- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
+++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
@@ -273,6 +273,22 @@ static Optional<Type> convertStructType(spirv::StructType type,
 
 namespace {
 
+class AddressOfPattern : public SPIRVToLLVMConversion<spirv::AddressOfOp> {
+public:
+  using SPIRVToLLVMConversion<spirv::AddressOfOp>::SPIRVToLLVMConversion;
+
+  LogicalResult
+  matchAndRewrite(spirv::AddressOfOp op, ArrayRef<Value> operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto dstType = typeConverter.convertType(op.pointer().getType());
+    if (!dstType)
+      return failure();
+    rewriter.replaceOpWithNewOp<LLVM::AddressOfOp>(
+        op, dstType.cast<LLVM::LLVMType>(), op.variable());
+    return success();
+  }
+};
+
 class BitFieldInsertPattern
     : public SPIRVToLLVMConversion<spirv::BitFieldInsertOp> {
 public:
@@ -507,6 +523,55 @@ class DirectConversionPattern : public SPIRVToLLVMConversion<SPIRVOp> {
   }
 };
 
+/// Converts `spv.globalVariable` to `llvm.mlir.global`. Note that SPIR-V global
+/// returns a pointer, whereas in LLVM dialect the global holds an actual value.
+/// This 
diff erence is handled by `spv._address_of` and `llvm.mlir.addressof`ops
+/// that both return a pointer.
+class GlobalVariablePattern
+    : public SPIRVToLLVMConversion<spirv::GlobalVariableOp> {
+public:
+  using SPIRVToLLVMConversion<spirv::GlobalVariableOp>::SPIRVToLLVMConversion;
+
+  LogicalResult
+  matchAndRewrite(spirv::GlobalVariableOp op, ArrayRef<Value> operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    // Currently, there is no support of initialization with a constant value in
+    // SPIR-V dialect. Specialization constants are not considered as well.
+    if (op.initializer())
+      return failure();
+
+    auto srcType = op.type().cast<spirv::PointerType>();
+    auto dstType = typeConverter.convertType(srcType.getPointeeType());
+    if (!dstType)
+      return failure();
+
+    // Limit conversion to the current invocation only for now.
+    auto storageClass = srcType.getStorageClass();
+    if (storageClass != spirv::StorageClass::Input &&
+        storageClass != spirv::StorageClass::Private &&
+        storageClass != spirv::StorageClass::Output) {
+      return failure();
+    }
+
+    // LLVM dialect spec: "If the global value is a constant, storing into it is
+    // not allowed.". This corresponds to SPIR-V 'Input' storage class that is
+    // read-only.
+    bool isConstant = storageClass == spirv::StorageClass::Input;
+    // SPIR-V spec: "By default, functions and global variables are private to a
+    // module and cannot be accessed by other modules. However, a module may be
+    // written to export or import functions and global (module scope)
+    // variables.". Therefore, map 'Private' storage class to private linkage,
+    // 'Input' and 'Output' to external linkage.
+    auto linkage = storageClass == spirv::StorageClass::Private
+                       ? LLVM::Linkage::Private
+                       : LLVM::Linkage::External;
+    rewriter.replaceOpWithNewOp<LLVM::GlobalOp>(
+        op, dstType.cast<LLVM::LLVMType>(), isConstant, linkage, op.sym_name(),
+        Attribute());
+    return success();
+  }
+};
+
 /// Converts SPIR-V cast ops that do not have straightforward LLVM
 /// equivalent in LLVM dialect.
 template <typename SPIRVOp, typename LLVMExtOp, typename LLVMTruncOp>
@@ -1230,8 +1295,8 @@ void mlir::populateSPIRVToLLVMConversionPatterns(
       NotPattern<spirv::LogicalNotOp>,
 
       // Memory ops
-      LoadStorePattern<spirv::LoadOp>, LoadStorePattern<spirv::StoreOp>,
-      VariablePattern,
+      AddressOfPattern, GlobalVariablePattern, LoadStorePattern<spirv::LoadOp>,
+      LoadStorePattern<spirv::StoreOp>, VariablePattern,
 
       // Miscellaneous ops
       DirectConversionPattern<spirv::SelectOp, LLVM::SelectOp>,

diff  --git a/mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir
index a565d396e6702..51a734c462a36 100644
--- a/mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir
+++ b/mlir/test/Conversion/SPIRVToLLVM/memory-ops-to-llvm.mlir
@@ -1,5 +1,25 @@
 // RUN: mlir-opt -convert-spirv-to-llvm %s | FileCheck %s
 
+//===----------------------------------------------------------------------===//
+// spv.globalVariable and spv._address_of
+//===----------------------------------------------------------------------===//
+
+spv.module Logical GLSL450 {
+  // CHECK: llvm.mlir.global external constant @var() : !llvm.float
+  spv.globalVariable @var : !spv.ptr<f32, Input>
+}
+
+spv.module Logical GLSL450 {
+  //       CHECK: llvm.mlir.global private @struct() : !llvm.struct<packed (float, array<10 x float>)>
+  // CHECK-LABEL: @func
+  //       CHECK: llvm.mlir.addressof @struct : !llvm.ptr<struct<packed (float, array<10 x float>)>>
+  spv.globalVariable @struct : !spv.ptr<!spv.struct<f32, !spv.array<10xf32>>, Private>
+  spv.func @func() -> () "None" {
+    %0 = spv._address_of @struct : !spv.ptr<!spv.struct<f32, !spv.array<10xf32>>, Private>
+    spv.Return
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // spv.Load
 //===----------------------------------------------------------------------===//


        


More information about the Mlir-commits mailing list