llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Adam Smith (adams381)

<details>
<summary>Changes</summary>

CIR now honors -mframe-pointer= the way classic CodeGen does. Functions and the 
module carry a new #cir.frame_pointer attribute, which lowers to the 
"frame-pointer" function attribute and module flag.

Assisted-by: Cursor / claude-opus-5.5


---

Patch is 29.72 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/230697.diff


14 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+45) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.td (+2) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+2-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+22-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+6) 
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+30-9) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+25) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp (+22) 
- (added) clang/test/CIR/CodeGen/frame-pointer.cpp (+93) 
- (modified) clang/test/CIR/IR/func-attrs.cir (+31) 
- (modified) clang/test/CIR/IR/invalid-func-attr.cir (+19) 
- (added) clang/test/CIR/IR/invalid-module-frame-pointer.cir (+19) 
- (added) clang/test/CIR/Lowering/frame-pointer.cir (+96) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index eb4cf65b919c4..e9eac89b34ec5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1454,6 +1454,51 @@ def CIR_UnwindTableKindAttr : 
CIR_EnumAttr<CIR_UnwindTableKind, "uwtable"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// FramePointerKind
+//===----------------------------------------------------------------------===//
+def CIR_FramePointerKind : CIR_I32Enum<"FramePointerKind",
+                                       "Frame Pointer Kind", [
+  I32EnumCase<"None", 0, "none">,
+  I32EnumCase<"NonLeaf", 1, "non_leaf">,
+  I32EnumCase<"All", 2, "all">,
+  I32EnumCase<"Reserved", 3, "reserved">,
+  I32EnumCase<"NonLeafNoReserve", 4, "non_leaf_no_reserve">
+]>;
+
+def CIR_FramePointerKindAttr
+    : CIR_EnumAttr<CIR_FramePointerKind, "frame_pointer"> {
+  let summary = "Encodes the frame pointer kind for a function or a module.";
+
+  let description = [{
+    This mirrors the FramePointerKind enum of the LLVM dialect.  On a
+    `cir.func` it is the `frame_pointer` attribute and lowers to the
+    `frame-pointer` function attribute in LLVM IR.  As the value of the
+    module attribute `cir.frame_pointer` it lowers to the `frame-pointer`
+    module flag, which LLVM gives to the functions it synthesizes.  A
+    function or module without the attribute behaves as `none`.
+
+    `none` lets the frame pointer be eliminated.  `all` keeps the frame
+    pointer, and `non_leaf` keeps it if the function calls other functions.
+    `reserved` lets the frame pointer be eliminated but keeps its register
+    from being used for anything else, so the register either points to a
+    valid frame record for the current function or is left unmodified.
+    `non_leaf_no_reserve` is `non_leaf`, except that a leaf function may use
+    the frame pointer register as a general-purpose register.
+
+    Example:
+
+    ```
+    module attributes {cir.frame_pointer = #cir.frame_pointer<all>} {
+      cir.func private @f() attributes {frame_pointer = 
#cir.frame_pointer<all>}
+      cir.func private @g() attributes {
+        frame_pointer = #cir.frame_pointer<non_leaf>
+      }
+    }
+    ```
+  }];
+}
+
 
//===----------------------------------------------------------------------===//
 // GloblCtorAttr
 
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 2086646949a11..c8cf2870a7eb5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -52,6 +52,7 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getNoReturnAttrName() { return "noreturn"; }
     static llvm::StringRef getMemoryEffectsAttrName() { return 
"memory_effects"; }
     static llvm::StringRef getUwtableAttrName() { return "uwtable"; }
+    static llvm::StringRef getFramePointerAttrName() { return "frame_pointer"; 
}
     static llvm::StringRef getReturnsTwiceAttrName() { return "returns_twice"; 
}
     static llvm::StringRef getColdAttrName() { return "cold"; }
     static llvm::StringRef getHotAttrName() { return "hot"; }
@@ -67,6 +68,7 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getNoUnwindAttrName() { return "nounwind"; }
     static llvm::StringRef getWillReturnAttrName() { return "willreturn"; }
     static llvm::StringRef getModuleLevelAsmAttrName() { return 
"cir.module_asm"; }
+    static llvm::StringRef getModuleFramePointerAttrName() { return 
"cir.frame_pointer"; }
     static llvm::StringRef getGlobalCtorsAttrName() { return 
"cir.global_ctors"; }
     static llvm::StringRef getGlobalDtorsAttrName() { return 
"cir.global_dtors"; }
     static llvm::StringRef getOffloadContainerAttrName() { return 
"cir.offload.container"; }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 53f693a7863ee..4c26dcf630ecc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4362,7 +4362,8 @@ def CIR_FuncOp : CIR_Op<"func", [
     CIR_OptionalPriorityAttr:$global_dtor_priority,
     OptionalAttr<CIR_FuncInfoAttr>:$func_info,
     OptionalAttr<CIR_AnnotationArrayAttr>:$annotations,
-    OptionalAttr<CIR_UnwindTableKindAttr>:$uwtable
+    OptionalAttr<CIR_UnwindTableKindAttr>:$uwtable,
+    OptionalAttr<CIR_FramePointerKindAttr>:$frame_pointer
   );
 
   let regions = (region AnyRegion:$body);
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index ec4dde920a270..6499f3dcceab5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -204,6 +204,23 @@ 
getZeroCallUsedRegsKindStr(llvm::ZeroCallUsedRegs::ZeroCallUsedRegsKind k) {
   llvm_unreachable("Unknown kind?");
 }
 
+std::optional<cir::FramePointerKind>
+CIRGenModule::getFramePointerKind(CodeGenOptions::FramePointerKind kind) {
+  switch (kind) {
+  case CodeGenOptions::FramePointerKind::None:
+    return std::nullopt;
+  case CodeGenOptions::FramePointerKind::Reserved:
+    return cir::FramePointerKind::Reserved;
+  case CodeGenOptions::FramePointerKind::NonLeafNoReserve:
+    return cir::FramePointerKind::NonLeafNoReserve;
+  case CodeGenOptions::FramePointerKind::NonLeaf:
+    return cir::FramePointerKind::NonLeaf;
+  case CodeGenOptions::FramePointerKind::All:
+    return cir::FramePointerKind::All;
+  }
+  llvm_unreachable("Unknown frame pointer kind");
+}
+
 /// Add default attributes to a function, which have merge semantics under
 /// -mlink-builtin-bitcode and should not simply overwrite any existing
 /// attributes in the linked library.
@@ -235,7 +252,11 @@ static void addTrivialDefaultFunctionAttributes(
       attrs.set(cir::CIRDialect::getTrapFuncNameAttrName(),
                 mlir::StringAttr::get(mlirCtx, codeGenOpts.TrapFuncName));
   } else {
-    // TODO(cir): Set frame pointer attribute here.
+    if (std::optional<cir::FramePointerKind> kind =
+            CIRGenModule::getFramePointerKind(codeGenOpts.getFramePointer()))
+      attrs.set(cir::CIRDialect::getFramePointerAttrName(),
+                cir::FramePointerKindAttr::get(mlirCtx, *kind));
+
     // TODO(cir): a number of other attribute 1-offs based on codegen/lang opts
     // should be done here: less-recise-fpmad null-pointer-is-valid
     // no-trapping-math
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 1f80f4e0ebf08..f4074aecb051c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -3923,6 +3923,12 @@ void CIRGenModule::release() {
 
   emitGlobalAnnotations();
 
+  if (std::optional<cir::FramePointerKind> kind =
+          getFramePointerKind(codeGenOpts.getFramePointer()))
+    theModule->setAttr(
+        cir::CIRDialect::getModuleFramePointerAttrName(),
+        cir::FramePointerKindAttr::get(&getMLIRContext(), *kind));
+
   if (!recordLayoutEntries.empty())
     theModule->setAttr(
         cir::CIRDialect::getRecordLayoutsAttrName(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 05ba8b5ee212e..ed5b7409eaa12 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -385,6 +385,12 @@ class CIRGenModule : public CIRGenTypeCache {
                                     bool attrOnCallSite,
                                     mlir::NamedAttrList &attrs);
 
+  /// Returns the frame pointer kind to record on functions and on the module,
+  /// or std::nullopt when \p kind is CodeGenOptions::FramePointerKind::None,
+  /// the default, which is left implicit.
+  static std::optional<cir::FramePointerKind>
+  getFramePointerKind(CodeGenOptions::FramePointerKind kind);
+
   /// Will return a global variable of the given type. If a variable with a
   /// different type already exists then a new variable with the right type
   /// will be created and all uses of the old variable will be replaced with a
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8a62ae541b4b6..96c6c05e0a11a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -272,6 +272,16 @@ cir::CIRDialect::verifyOperationAttribute(mlir::Operation 
*op,
                              << "' attribute to be attached to '"
                              << mlir::ModuleOp::getOperationName() << "'";
 
+  if (attrName == getModuleFramePointerAttrName()) {
+    if (!mlir::isa<mlir::ModuleOp>(op))
+      return op->emitOpError() << "expects '" << 
getModuleFramePointerAttrName()
+                               << "' attribute to be attached to '"
+                               << mlir::ModuleOp::getOperationName() << "'";
+    if (!mlir::isa<cir::FramePointerKindAttr>(attr.getValue()))
+      return op->emitOpError() << "expects '" << 
getModuleFramePointerAttrName()
+                               << "' to be a #cir.frame_pointer attribute";
+  }
+
   // LoweringPrepare uses this attribute directly as the fatbin global's
   // initializer, so it must be a valid #cir.const_array payload for its type.
   if (attrName == getCUDADeviceBinaryAttrName()) {
@@ -1371,9 +1381,10 @@ parseTryCallDestinations(mlir::OpAsmParser &parser,
   return mlir::success();
 }
 
-/// Reject an effect attribute of the wrong kind in an explicit attribute
-/// dictionary.  Where these are declared they are stored as properties, so a
-/// value of the wrong kind would be dropped without a diagnostic.
+/// Reject an attribute in an explicit attribute dictionary whose value is not
+/// the attribute class expected for its name.  Where an op declares the
+/// attribute it is stored as a property, so a value of the wrong class would
+/// be dropped without a diagnostic.
 static ParseResult checkEffectAttrKinds(mlir::OpAsmParser &parser,
                                         llvm::SMLoc loc,
                                         const mlir::NamedAttrList &attrs) {
@@ -1390,6 +1401,13 @@ static ParseResult 
checkEffectAttrKinds(mlir::OpAsmParser &parser,
              << CIRDialect::getUwtableAttrName()
              << "' must be a #cir.uwtable attribute";
 
+  if (mlir::Attribute framePointer =
+          attrs.get(CIRDialect::getFramePointerAttrName()))
+    if (!mlir::isa<cir::FramePointerKindAttr>(framePointer))
+      return parser.emitError(loc, "attribute '")
+             << CIRDialect::getFramePointerAttrName()
+             << "' must be a #cir.frame_pointer attribute";
+
   for (llvm::StringRef name :
        {CIRDialect::getNoUnwindAttrName(), CIRDialect::getWillReturnAttrName(),
         CIRDialect::getMustProgressAttrName()})
@@ -3098,11 +3116,13 @@ ParseResult cir::FuncOp::parse(OpAsmParser &parser, 
OperationState &state) {
     return failure();
 
   // Every other declared attribute has dedicated syntax above, so
-  // memory_effects and uwtable is the only one the explicit list may carry.
-  // Without the exception cir.func could not parse back what it prints.
+  // memory_effects, uwtable and frame_pointer are the only ones the explicit
+  // list may carry.  Without these exceptions cir.func could not parse back
+  // what it prints.
   for (StringRef disallowed : cir::FuncOp::getAttributeNames()) {
     if (disallowed == CIRDialect::getMemoryEffectsAttrName() ||
-        disallowed == CIRDialect::getUwtableAttrName())
+        disallowed == CIRDialect::getUwtableAttrName() ||
+        disallowed == CIRDialect::getFramePointerAttrName())
       continue;
     if (parsedAttrs.get(disallowed))
       return parser.emitError(loc, "attribute '")
@@ -3295,12 +3315,13 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
   }
 
   // Every declared attribute is printed by the syntax above, except
-  // memory_effects and uwtable, which have none and so must reach the
-  // dictionary.
+  // memory_effects, uwtable and frame_pointer, which have none and so must
+  // reach the dictionary.
   llvm::SmallVector<llvm::StringRef> elidedAttrs;
   for (llvm::StringRef name : cir::FuncOp::getAttributeNames())
     if (name != CIRDialect::getMemoryEffectsAttrName() &&
-        name != CIRDialect::getUwtableAttrName())
+        name != CIRDialect::getUwtableAttrName() &&
+        name != CIRDialect::getFramePointerAttrName())
       elidedAttrs.push_back(name);
   function_interface_impl::printFunctionAttributes(p, *this, elidedAttrs);
 
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index d919ed2e98a5b..11679fbe53091 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -305,6 +305,26 @@ convertUWTableKind(cir::UnwindTableKind kind) {
   llvm_unreachable("Unknown CIR unwind table kind");
 }
 
+static mlir::LLVM::framePointerKind::FramePointerKind
+convertFramePointerKind(cir::FramePointerKind kind) {
+  using CIR = cir::FramePointerKind;
+  using LLVM = mlir::LLVM::framePointerKind::FramePointerKind;
+
+  switch (kind) {
+  case CIR::None:
+    return LLVM::None;
+  case CIR::NonLeaf:
+    return LLVM::NonLeaf;
+  case CIR::All:
+    return LLVM::All;
+  case CIR::Reserved:
+    return LLVM::Reserved;
+  case CIR::NonLeafNoReserve:
+    return LLVM::NonLeafNoReserve;
+  }
+  llvm_unreachable("Unknown CIR frame pointer kind");
+}
+
 mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
     cir::CopyOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
@@ -2933,6 +2953,11 @@ mlir::LogicalResult 
CIRToLLVMFuncOpLowering::matchAndRewrite(
     fn.setUwtableKindAttr(mlir::LLVM::UWTableKindAttr::get(
         fn.getContext(), convertUWTableKind(*uwtableKind)));
 
+  if (std::optional<cir::FramePointerKind> framePointerKind =
+          op.getFramePointer())
+    fn.setFramePointerAttr(mlir::LLVM::FramePointerKindAttr::get(
+        fn.getContext(), convertFramePointerKind(*framePointerKind)));
+
   // Function attributes with no dedicated field on the LLVM dialect's
   // LLVMFuncOp are routed through the `passthrough` array. The MLIR LLVM IR
   // translator forwards `passthrough` entries to LLVM IR as function
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
index 213f80f0defb0..71f59bafdb7c9 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVMIR.cpp
@@ -27,6 +27,23 @@ using namespace llvm;
 namespace cir {
 namespace direct {
 
+static llvm::FramePointerKind
+convertFramePointerKind(cir::FramePointerKind kind) {
+  switch (kind) {
+  case cir::FramePointerKind::None:
+    return llvm::FramePointerKind::None;
+  case cir::FramePointerKind::NonLeaf:
+    return llvm::FramePointerKind::NonLeaf;
+  case cir::FramePointerKind::All:
+    return llvm::FramePointerKind::All;
+  case cir::FramePointerKind::Reserved:
+    return llvm::FramePointerKind::Reserved;
+  case cir::FramePointerKind::NonLeafNoReserve:
+    return llvm::FramePointerKind::NonLeafNoReserve;
+  }
+  llvm_unreachable("Unknown CIR frame pointer kind");
+}
+
 /// Implementation of the dialect interface that converts CIR attributes to 
LLVM
 /// IR metadata.
 class CIRDialectLLVMIRTranslationInterface
@@ -135,6 +152,11 @@ class CIRDialectLLVMIRTranslationInterface
     llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
     llvm::LLVMContext &llvmContext = llvmModule->getContext();
 
+    if (attribute.getName() == 
cir::CIRDialect::getModuleFramePointerAttrName())
+      llvmModule->setFramePointer(convertFramePointerKind(
+          mlir::cast<cir::FramePointerKindAttr>(attribute.getValue())
+              .getValue()));
+
     if (attribute.getName() == "cir.amdhsa_code_object_version") {
       if (auto intAttr =
               mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue())) {
diff --git a/clang/test/CIR/CodeGen/frame-pointer.cpp 
b/clang/test/CIR/CodeGen/frame-pointer.cpp
new file mode 100644
index 0000000000000..a99ac0c20e309
--- /dev/null
+++ b/clang/test/CIR/CodeGen/frame-pointer.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t-default.cir
+// RUN: FileCheck --input-file=%t-default.cir %s --check-prefix=CIR-NONE
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-default-cir.ll
+// RUN: FileCheck --input-file=%t-default-cir.ll %s --check-prefix=LLVM-NONE
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o 
%t-default.ll
+// RUN: FileCheck --input-file=%t-default.ll %s --check-prefix=LLVM-NONE
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=none 
-fclangir -emit-cir %s -o %t-none.cir
+// RUN: FileCheck --input-file=%t-none.cir %s --check-prefix=CIR-NONE
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=none 
-fclangir -emit-llvm %s -o %t-none-cir.ll
+// RUN: FileCheck --input-file=%t-none-cir.ll %s --check-prefix=LLVM-NONE
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=none 
-emit-llvm %s -o %t-none.ll
+// RUN: FileCheck --input-file=%t-none.ll %s --check-prefix=LLVM-NONE
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=non-leaf 
-fclangir -emit-cir %s -o %t-non-leaf.cir
+// RUN: FileCheck --input-file=%t-non-leaf.cir %s --check-prefix=CIR-NON-LEAF
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=non-leaf 
-fclangir -emit-llvm %s -o %t-non-leaf-cir.ll
+// RUN: FileCheck --input-file=%t-non-leaf-cir.ll %s 
--check-prefix=LLVM-NON-LEAF
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=non-leaf 
-emit-llvm %s -o %t-non-leaf.ll
+// RUN: FileCheck --input-file=%t-non-leaf.ll %s --check-prefix=LLVM-NON-LEAF
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=all 
-fclangir -emit-cir %s -o %t-all.cir
+// RUN: FileCheck --input-file=%t-all.cir %s --check-prefix=CIR-ALL
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=all 
-fclangir -emit-llvm %s -o %t-all-cir.ll
+// RUN: FileCheck --input-file=%t-all-cir.ll %s --check-prefix=LLVM-ALL
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=all 
-emit-llvm %s -o %t-all.ll
+// RUN: FileCheck --input-file=%t-all.ll %s --check-prefix=LLVM-ALL
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=reserved 
-fclangir -emit-cir %s -o %t-reserved.cir
+// RUN: FileCheck --input-file=%t-reserved.cir %s --check-prefix=CIR-RESERVED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=reserved 
-fclangir -emit-llvm %s -o %t-reserved-cir.ll
+// RUN: FileCheck --input-file=%t-reserved-cir.ll %s 
--check-prefix=LLVM-RESERVED
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mframe-pointer=reserved 
-emit-llvm %s -o %t-reserved.ll
+// RUN: FileCheck --input-file=%t-reserved.ll %s --check-prefix=LLVM-RESERVED
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-mframe-pointer=non-leaf-no-reserve -fclangir -emit-cir %s -o %t-nlnr.cir
+// RUN: FileCheck --input-file=%t-nlnr.cir %s --check-prefix=CIR-NLNR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-mframe-pointer=non-leaf-no-reserve -fclangir -emit-llvm %s -o %t-nlnr-cir.ll
+// RUN: FileCheck --input-file=%t-nlnr-cir.ll %s --check-prefix=LLVM-NLNR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-mframe-pointer=non-leaf-no-reserve -emit-llvm %s -o %t-nlnr.ll
+// RUN: FileCheck --input-file=%t-nlnr.ll %s --check-prefix=LLVM-NLNR
+
+void declaration();
+void definition() { declaration(); }
+
+// CIR-NONE-NOT: frame_pointer
+// CIR-NONE: cir.func {{.*}}@_Z10definitionv()
+// CIR-NONE-NOT: frame_pointer
+
+// CIR-NON-LEAF: module {{.*}}attributes {{.*}}cir.frame_pointer = 
#cir.frame_pointer<non_leaf>
+// CIR-NON-LEAF: cir.func {{.*}}@_Z10definitionv() attributes 
{{.*}}frame_pointer = #cir.frame_pointer<non_leaf>
+// CIR-NON-LEAF: cir.func private @_Z11declarationv() attributes 
{{.*}}frame_pointer = #cir.frame_pointer<non_leaf>
+
+// CIR-ALL: module {{.*}}attributes {{.*}}cir.frame_pointer = 
#cir.frame_pointer<all>
+// CIR-ALL: cir.func {{.*}}@_Z10definitionv() attributes {{.*}}frame_pointer = 
#cir.frame_point...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/230697
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to