[Mlir-commits] [mlir] 13cb085 - [mlir] Support llvm.readnone attribute for all FunctionOpInterface ops.

Slava Zakharin llvmlistbot at llvm.org
Wed Aug 24 10:13:57 PDT 2022


Author: Slava Zakharin
Date: 2022-08-24T10:12:37-07:00
New Revision: 13cb085ca1dfc7f4bf62b642a69b1dd17f1fd01e

URL: https://github.com/llvm/llvm-project/commit/13cb085ca1dfc7f4bf62b642a69b1dd17f1fd01e
DIFF: https://github.com/llvm/llvm-project/commit/13cb085ca1dfc7f4bf62b642a69b1dd17f1fd01e.diff

LOG: [mlir] Support llvm.readnone attribute for all FunctionOpInterface ops.

The attribute is translated into LLVM's function attribute 'readnone'.
There is no explicit verification regarding conflicting 'readnone'
and function attributes from 'passthrough', though, LLVM would assert
if they are incompatible during LLVM IR creation.

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

Added: 
    mlir/test/Target/LLVMIR/Import/function_attributes.ll

Modified: 
    mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
    mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
    mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
    mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
    mlir/test/Dialect/LLVMIR/func.mlir
    mlir/test/Target/LLVMIR/llvmir.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
index 3c63cdc487a98..bd6d8a1c7ad25 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td
@@ -66,6 +66,12 @@ def LLVM_Dialect : Dialect {
     /// Returns `true` if the given type is compatible with the LLVM dialect.
     static bool isCompatibleType(Type);
 
+    /// Name of the attribute mapped to LLVM's 'readnone' function attribute.
+    /// It is allowed on any FunctionOpInterface operations.
+    static StringRef getReadnoneAttrName() {
+      return "llvm.readnone";
+    }
+
   private:
     /// A cache storing compatible LLVM types that have been verified. This
     /// can save us lots of verification time if there are many occurrences

diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 35c215c07a9fe..36e19702279a5 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2683,6 +2683,17 @@ LogicalResult LLVMDialect::verifyOperationAttribute(Operation *op,
              << "' to be a `loopopts` attribute";
   }
 
+  if (attr.getName() == LLVMDialect::getReadnoneAttrName()) {
+    const auto attrName = LLVMDialect::getReadnoneAttrName();
+    if (!isa<FunctionOpInterface>(op))
+      return op->emitOpError()
+             << "'" << attrName
+             << "' is permitted only on FunctionOpInterface operations";
+    if (!attr.getValue().isa<UnitAttr>())
+      return op->emitOpError()
+             << "expected '" << attrName << "' to be a unit attribute";
+  }
+
   if (attr.getName() == LLVMDialect::getStructAttrsAttrName()) {
     return op->emitOpError()
            << "'" << LLVM::LLVMDialect::getStructAttrsAttrName()

diff  --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
index 54391b86a547a..160d9396c5b00 100644
--- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
@@ -168,6 +168,10 @@ class Importer {
   /// Imports `f` into the current module.
   LogicalResult processFunction(llvm::Function *f);
 
+  /// Converts function attributes of LLVM Function \p f
+  /// into LLVM dialect attributes of LLVMFuncOp \p funcOp.
+  void processFunctionAttributes(llvm::Function *f, LLVMFuncOp funcOp);
+
   /// Imports GV as a GlobalOp, creating it if it doesn't exist.
   GlobalOp processGlobal(llvm::GlobalVariable *gv);
 
@@ -1157,6 +1161,15 @@ FlatSymbolRefAttr Importer::getPersonalityAsAttr(llvm::Function *f) {
   return FlatSymbolRefAttr();
 }
 
+void Importer::processFunctionAttributes(llvm::Function *func,
+                                         LLVMFuncOp funcOp) {
+  auto addNamedUnitAttr = [&](StringRef name) {
+    return funcOp->setAttr(name, UnitAttr::get(context));
+  };
+  if (func->hasFnAttribute(llvm::Attribute::ReadNone))
+    addNamedUnitAttr(LLVMDialect::getReadnoneAttrName());
+}
+
 LogicalResult Importer::processFunction(llvm::Function *f) {
   blocks.clear();
   instMap.clear();
@@ -1191,6 +1204,9 @@ LogicalResult Importer::processFunction(llvm::Function *f) {
   if (f->hasGC())
     fop.setGarbageCollectorAttr(b.getStringAttr(f->getGC()));
 
+  // Handle Function attributes.
+  processFunctionAttributes(f, fop);
+
   if (f->isDeclaration())
     return success();
 

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4855571c05bd5..0464cfc825c1f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -927,6 +927,9 @@ LogicalResult ModuleTranslation::convertFunctionSignatures() {
     mapFunction(function.getName(), llvmFunc);
     addRuntimePreemptionSpecifier(function.getDsoLocal(), llvmFunc);
 
+    if (function->getAttrOfType<UnitAttr>(LLVMDialect::getReadnoneAttrName()))
+      llvmFunc->addFnAttr(llvm::Attribute::ReadNone);
+
     // Forward the pass-through attributes to LLVM.
     if (failed(forwardPassthroughAttributes(
             function.getLoc(), function.getPassthrough(), llvmFunc)))

diff  --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index b19846eaca7df..9c2b973a67aad 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -277,3 +277,21 @@ module {
   "llvm.func"() ({
   }) {sym_name = "generic_unknown_calling_convention", CConv = #llvm.cconv<cc_12>, function_type = !llvm.func<i64 (i64, i64)>} : () -> ()
 }
+
+// -----
+
+module {
+  // expected-error at +3 {{'llvm.readnone' is permitted only on FunctionOpInterface operations}}
+  "llvm.func"() ({
+  ^bb0:
+    llvm.return {llvm.readnone}
+  }) {sym_name = "readnone_return", function_type = !llvm.func<void ()>} : () -> ()
+}
+
+// -----
+
+module {
+  // expected-error at +1 {{op expected 'llvm.readnone' to be a unit attribute}}
+  "llvm.func"() ({
+  }) {sym_name = "readnone_func", llvm.readnone = true, function_type = !llvm.func<void ()>} : () -> ()
+}

diff  --git a/mlir/test/Target/LLVMIR/Import/function_attributes.ll b/mlir/test/Target/LLVMIR/Import/function_attributes.ll
new file mode 100644
index 0000000000000..8588b88a96657
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/function_attributes.ll
@@ -0,0 +1,17 @@
+; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+
+// -----
+
+; CHECK: llvm.func @readnone_attr() attributes {llvm.readnone}
+declare void @readnone_attr() #0
+attributes #0 = { readnone }
+
+// -----
+
+; CHECK: llvm.func @readnone_attr() attributes {llvm.readnone} {
+; CHECK:   llvm.return
+; CHECK: }
+define void @readnone_attr() readnone {
+entry:
+  ret void
+}

diff  --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index b57cc50620534..3b68340cf7629 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -1937,3 +1937,11 @@ llvm.func @vararg_function(%arg0: i32, ...) {
   // CHECK: ret void
   llvm.return
 }
+
+// -----
+
+// Function attributes: readnone
+
+// CHECK: declare void @readnone_function() #[[ATTR:[0-9]+]]
+// CHECK: attributes #[[ATTR]] = { readnone }
+llvm.func @readnone_function() attributes {llvm.readnone}


        


More information about the Mlir-commits mailing list