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

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Nov 13 10:13:43 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-llvm

Author: Radu Salavat (Radu2k)

<details>
<summary>Changes</summary>

Add support for frame pointers in MLIR.

---
Full diff: https://github.com/llvm/llvm-project/pull/72145.diff


8 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td (+19) 
- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td (+2-1) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp (+23-2) 
- (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+10-1) 
- (modified) mlir/lib/Target/LLVMIR/ModuleTranslation.cpp (+4) 
- (modified) mlir/test/Dialect/LLVMIR/func.mlir (+6) 
- (added) mlir/test/Target/LLVMIR/Import/frame-pointer.ll (+7) 
- (added) mlir/test/Target/LLVMIR/frame-pointer.mlir (+8) 


``````````diff
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
+}
+

``````````

</details>


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


More information about the Mlir-commits mailing list