[Mlir-commits] [mlir] [MLIR] Add support for frame pointers in MLIR (PR #72145)

Radu Salavat llvmlistbot at llvm.org
Wed Nov 15 03:38:40 PST 2023


https://github.com/Radu2k updated https://github.com/llvm/llvm-project/pull/72145

>From d53a30813d5ab1ffcb1f9a5844af3ea782361c38 Mon Sep 17 00:00:00 2001
From: Radu2k <radusalavat48 at gmail.com>
Date: Mon, 13 Nov 2023 17:57:24 +0000
Subject: [PATCH 1/3] [MLIR] Add support for frame pointers in MLIR

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td | 19 ++++++++++++++
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |  3 ++-
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    | 25 +++++++++++++++++--
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       | 11 +++++++-
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  4 +++
 mlir/test/Dialect/LLVMIR/func.mlir            |  6 +++++
 .../Target/LLVMIR/Import/frame-pointer.ll     |  7 ++++++
 mlir/test/Target/LLVMIR/frame-pointer.mlir    |  8 ++++++
 8 files changed, 79 insertions(+), 4 deletions(-)
 create mode 100644 mlir/test/Target/LLVMIR/Import/frame-pointer.ll
 create mode 100644 mlir/test/Target/LLVMIR/frame-pointer.mlir

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
index f05230526c21f55..446850d6dc7bb96 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
@@ -664,4 +664,23 @@ def ModRefInfoEnum : LLVM_EnumAttr<
   let cppNamespace = "::mlir::LLVM";
 }
 
+//===----------------------------------------------------------------------===//
+// FramePointerAttr
+//===----------------------------------------------------------------------===//
+
+def FramePointerKindNone
+    : LLVM_EnumAttrCase<"None", "none", "None", 0>;
+def FramePointerKindNonLeaf
+    : LLVM_EnumAttrCase<"NonLeaf", "non-leaf", "NonLeaf", 1>;
+def FramePointerKindAll
+    : LLVM_EnumAttrCase<"All", "all", "All", 2>;
+
+def FramePointerKindAttr : LLVM_EnumAttr<
+    "FramePointerKind",
+    "::llvm::FramePointerKind",
+    "LLVM FramePointerKind",
+    [FramePointerKindNone, FramePointerKindNonLeaf, FramePointerKindAll]> {
+  let cppNamespace = "::mlir::LLVM";
+}
+
 #endif // LLVMIR_ENUMS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 9fa6f23ce4de2dd..3feb20bc9faa4f2 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1390,7 +1390,8 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<StrAttr>:$section,
     OptionalAttr<UnnamedAddr>:$unnamed_addr,
     OptionalAttr<I64Attr>:$alignment,
-    OptionalAttr<LLVM_VScaleRangeAttr>:$vscale_range
+    OptionalAttr<LLVM_VScaleRangeAttr>:$vscale_range,
+    OptionalAttr<FramePointerKindAttr>:$frame_pointer
   );
 
   let regions = (region AnyRegion:$body);
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index f6c8f388732c3da..510d81e46cbb43a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2309,7 +2309,7 @@ ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
                                    IntegerAttr::get(intTy, minRange),
                                    IntegerAttr::get(intTy, maxRange)));
   }
-  // Parse the optional comdat selector.
+  // Parse the optional comdat selector.:q
   if (succeeded(parser.parseOptionalKeyword("comdat"))) {
     SymbolRefAttr comdat;
     if (parser.parseLParen() || parser.parseAttribute(comdat) ||
@@ -2319,6 +2319,23 @@ ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
     result.addAttribute(getComdatAttrName(result.name), comdat);
   }
 
+  // Parse the optional frame_pointer
+  if (succeeded(parser.parseOptionalKeyword("frame_pointer"))) {
+    std::string string;
+    
+    if (parser.parseEqual() || parser.parseString(&string))
+      return failure();
+    if (!LLVM::symbolizeFramePointerKind(string))
+    { 
+      llvm::outs() << "failure: frame-pointer option not recognized: " << string << "\n";
+      return failure();
+    }
+
+    result.addAttribute(getFramePointerAttrName(result.name), 
+        LLVM::FramePointerKindAttr::get(parser.getContext(),
+                                   LLVM::symbolizeFramePointerKind(string).value()));
+  }
+
   if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
     return failure();
   function_interface_impl::addArgAndResultAttrs(
@@ -2373,13 +2390,17 @@ void LLVMFuncOp::print(OpAsmPrinter &p) {
   // Print the optional comdat selector.
   if (auto comdat = getComdat())
     p << " comdat(" << *comdat << ')';
+  
+  // Print the optional frame pointer option.
+  if (std::optional<FramePointerKind> frame_pointer = getFramePointer())
+    p << " frame_pointer=" << "\"" << stringifyFramePointerKind(frame_pointer.value()) << "\"";
 
   function_interface_impl::printFunctionAttributes(
       p, *this,
       {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
        getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
        getComdatAttrName(), getUnnamedAddrAttrName(),
-       getVscaleRangeAttrName()});
+       getVscaleRangeAttrName(), getFramePointerAttrName()});
 
   // Print the body if this is not an external function.
   Region &body = getBody();
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index dd2da66caf428bf..e3b08ce4e868b7f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1602,7 +1602,9 @@ static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {
     // explicit attribute.
     // Also skip the vscale_range, it is also an explicit attribute.
     if (attrName == "aarch64_pstate_sm_enabled" ||
-        attrName == "aarch64_pstate_sm_body" || attrName == "vscale_range")
+        attrName == "aarch64_pstate_sm_body" || 
+        attrName == "vscale_range" || 
+        attrName == "frame-pointer")
       continue;
 
     if (attr.isStringAttribute()) {
@@ -1650,6 +1652,13 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func,
         context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
         IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
   }
+
+  // Process frame-pointer attribute
+  if (func->hasFnAttribute("frame-pointer")) {
+    llvm::StringRef stringRefFramePointerKind = func->getFnAttribute("frame-pointer").getValueAsString();
+    funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(funcOp.getContext(),
+                                  symbolizeFramePointerKind(stringRefFramePointerKind).value()));
+  }
 }
 
 DictionaryAttr
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 388ae61958b78b9..d97d4a1b1e50b2d 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -894,6 +894,10 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
     llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
         getLLVMContext(), attr->getMinRange().getInt(),
         attr->getMaxRange().getInt()));
+  
+  // Add function attribute frame-pointer, if found.
+  if (auto attr = func.getFramePointerAttr()) 
+    llvmFunc->addFnAttr("frame-pointer", stringifyFramePointerKind(attr.getValue()));
 
   // First, create all blocks so we can jump to them.
   llvm::LLVMContext &llvmContext = llvmFunc->getContext();
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index 63e20b1d8fc31ab..9e68a3dff4bca85 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -249,6 +249,12 @@ module {
     // CHECK-SAME: vscale_range(1, 2)
     llvm.return
   }
+
+  llvm.func @frame_pointer_roundtrip() frame_pointer="non-leaf" {
+    // CHECK: @frame_pointer_roundtrip()
+    // CHECK-SAME: frame_pointer="non-leaf"
+    llvm.return
+  }
 }
 
 // -----
diff --git a/mlir/test/Target/LLVMIR/Import/frame-pointer.ll b/mlir/test/Target/LLVMIR/Import/frame-pointer.ll
new file mode 100644
index 000000000000000..698771f4ae04c3e
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/frame-pointer.ll
@@ -0,0 +1,7 @@
+; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+
+define void @frame_pointer_func() "frame-pointer"="non-leaf" {
+  ; CHECK: llvm.func @frame_pointer_func()
+  ; CHECK-SAME: frame_pointer="non-leaf"
+  ret void
+}
diff --git a/mlir/test/Target/LLVMIR/frame-pointer.mlir b/mlir/test/Target/LLVMIR/frame-pointer.mlir
new file mode 100644
index 000000000000000..543b6b1af1761b8
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/frame-pointer.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+llvm.func @frame_pointer_func() frame_pointer="non-leaf" {
+  // CHECK-LABEL: define void @frame_pointer_func
+  // CHECK: attributes #{{.*}} = { "frame-pointer"="non-leaf" }
+  llvm.return
+}
+

>From a8c63fbd8058e6fc029e8b4679263b986971c8e3 Mon Sep 17 00:00:00 2001
From: Radu Salavat <radusalavat48 at gmail.com>
Date: Tue, 14 Nov 2023 11:52:28 +0000
Subject: [PATCH 2/3] Update mlir/test/Target/LLVMIR/frame-pointer.mlir
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Markus Böck <markus.boeck02 at gmail.com>
---
 mlir/test/Target/LLVMIR/frame-pointer.mlir | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/frame-pointer.mlir b/mlir/test/Target/LLVMIR/frame-pointer.mlir
index 543b6b1af1761b8..f69cd18e0577f9f 100644
--- a/mlir/test/Target/LLVMIR/frame-pointer.mlir
+++ b/mlir/test/Target/LLVMIR/frame-pointer.mlir
@@ -1,8 +1,8 @@
 // RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
 
 llvm.func @frame_pointer_func() frame_pointer="non-leaf" {
-  // CHECK-LABEL: define void @frame_pointer_func
-  // CHECK: attributes #{{.*}} = { "frame-pointer"="non-leaf" }
+  // CHECK-LABEL: define void @frame_pointer_func() #[[ATTRS:\d+]]
+  // CHECK: attributes #[[ATTRS]] = { "frame-pointer"="non-leaf" }
   llvm.return
 }
 

>From b27cf55fd13f1e9cbb7a8aeecbc2618e3b432521 Mon Sep 17 00:00:00 2001
From: Radu2k <radusalavat48 at gmail.com>
Date: Tue, 14 Nov 2023 23:22:57 +0000
Subject: [PATCH 3/3] Removed special syntax for handling the frame pointer
 attribute for llvm.func op parser and printer, spelled out 'auto' and
 enhanced the mlir-to-llvmir check by adding ATTRS as variable

---
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    | 23 +------------------
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  2 +-
 mlir/test/Dialect/LLVMIR/func.mlir            |  4 ++--
 .../Target/LLVMIR/Import/frame-pointer.ll     |  3 ++-
 mlir/test/Target/LLVMIR/frame-pointer.mlir    |  5 ++--
 5 files changed, 9 insertions(+), 28 deletions(-)

diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 510d81e46cbb43a..696de2bdb8f36d4 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2319,23 +2319,6 @@ ParseResult LLVMFuncOp::parse(OpAsmParser &parser, OperationState &result) {
     result.addAttribute(getComdatAttrName(result.name), comdat);
   }
 
-  // Parse the optional frame_pointer
-  if (succeeded(parser.parseOptionalKeyword("frame_pointer"))) {
-    std::string string;
-    
-    if (parser.parseEqual() || parser.parseString(&string))
-      return failure();
-    if (!LLVM::symbolizeFramePointerKind(string))
-    { 
-      llvm::outs() << "failure: frame-pointer option not recognized: " << string << "\n";
-      return failure();
-    }
-
-    result.addAttribute(getFramePointerAttrName(result.name), 
-        LLVM::FramePointerKindAttr::get(parser.getContext(),
-                                   LLVM::symbolizeFramePointerKind(string).value()));
-  }
-
   if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
     return failure();
   function_interface_impl::addArgAndResultAttrs(
@@ -2390,17 +2373,13 @@ void LLVMFuncOp::print(OpAsmPrinter &p) {
   // Print the optional comdat selector.
   if (auto comdat = getComdat())
     p << " comdat(" << *comdat << ')';
-  
-  // Print the optional frame pointer option.
-  if (std::optional<FramePointerKind> frame_pointer = getFramePointer())
-    p << " frame_pointer=" << "\"" << stringifyFramePointerKind(frame_pointer.value()) << "\"";
 
   function_interface_impl::printFunctionAttributes(
       p, *this,
       {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
        getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
        getComdatAttrName(), getUnnamedAddrAttrName(),
-       getVscaleRangeAttrName(), getFramePointerAttrName()});
+       getVscaleRangeAttrName()});
 
   // Print the body if this is not an external function.
   Region &body = getBody();
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index d97d4a1b1e50b2d..a4b80481b4f3c9c 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -896,7 +896,7 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
         attr->getMaxRange().getInt()));
   
   // Add function attribute frame-pointer, if found.
-  if (auto attr = func.getFramePointerAttr()) 
+  if (mlir::LLVM::FramePointerKindAttr attr = func.getFramePointerAttr())
     llvmFunc->addFnAttr("frame-pointer", stringifyFramePointerKind(attr.getValue()));
 
   // First, create all blocks so we can jump to them.
diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir
index 9e68a3dff4bca85..ab9889c7b279034 100644
--- a/mlir/test/Dialect/LLVMIR/func.mlir
+++ b/mlir/test/Dialect/LLVMIR/func.mlir
@@ -250,9 +250,9 @@ module {
     llvm.return
   }
 
-  llvm.func @frame_pointer_roundtrip() frame_pointer="non-leaf" {
+  llvm.func @frame_pointer_roundtrip() attributes {frame_pointer = 1 : i64} {
     // CHECK: @frame_pointer_roundtrip()
-    // CHECK-SAME: frame_pointer="non-leaf"
+    // CHECK-SAME: attributes {frame_pointer = 1 : i64}
     llvm.return
   }
 }
diff --git a/mlir/test/Target/LLVMIR/Import/frame-pointer.ll b/mlir/test/Target/LLVMIR/Import/frame-pointer.ll
index 698771f4ae04c3e..8f8eec66913ce44 100644
--- a/mlir/test/Target/LLVMIR/Import/frame-pointer.ll
+++ b/mlir/test/Target/LLVMIR/Import/frame-pointer.ll
@@ -2,6 +2,7 @@
 
 define void @frame_pointer_func() "frame-pointer"="non-leaf" {
   ; CHECK: llvm.func @frame_pointer_func()
-  ; CHECK-SAME: frame_pointer="non-leaf"
+  ; CHECK-SAME: attributes {frame_pointer = 1 : i64}   
+  
   ret void
 }
diff --git a/mlir/test/Target/LLVMIR/frame-pointer.mlir b/mlir/test/Target/LLVMIR/frame-pointer.mlir
index f69cd18e0577f9f..39057b28d5b2890 100644
--- a/mlir/test/Target/LLVMIR/frame-pointer.mlir
+++ b/mlir/test/Target/LLVMIR/frame-pointer.mlir
@@ -1,7 +1,8 @@
 // RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
 
-llvm.func @frame_pointer_func() frame_pointer="non-leaf" {
-  // CHECK-LABEL: define void @frame_pointer_func() #[[ATTRS:\d+]]
+llvm.func @frame_pointer_func() attributes {frame_pointer = 1 : i64}  {
+  // CHECK-LABEL: define void @frame_pointer_func() 
+  // CHECK-SAME: #[[ATTRS:[0-9]+]]
   // CHECK: attributes #[[ATTRS]] = { "frame-pointer"="non-leaf" }
   llvm.return
 }



More information about the Mlir-commits mailing list