[clang] [CIR] Upstream StackSave and StackRestoreOp (PR #136426)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 21 03:48:08 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/136426
>From 91a6937c7b937daceef426c877703d4d0cfeae76 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sat, 19 Apr 2025 14:22:45 +0200
Subject: [PATCH 1/2] [CIR] Upstream StackSave and StackRestoreOp
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 42 +++++++++++++++++++
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++++++
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 20 +++++++++
clang/test/CIR/IR/stack-save-restore.cir | 23 ++++++++++
.../test/CIR/Lowering/stack-save-restore.cir | 19 +++++++++
5 files changed, 122 insertions(+)
create mode 100644 clang/test/CIR/IR/stack-save-restore.cir
create mode 100644 clang/test/CIR/Lowering/stack-save-restore.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5ba4b33dc1a12..2b48aac97e7ef 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1419,6 +1419,48 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
}]>];
}
+//===----------------------------------------------------------------------===//
+// StackSave & StackRestoreOp
+//===----------------------------------------------------------------------===//
+
+def StackSaveOp : CIR_Op<"stack_save"> {
+ let summary = "remembers the current state of the function stack";
+ let description = [{
+ Remembers the current state of the function stack. Returns a pointer
+ that later can be passed into cir.stack_restore.
+ Useful for implementing language features like variable length arrays.
+
+ ```mlir
+ %0 = cir.stack_save : <!u8i>
+ ```
+ }];
+
+ let results = (outs CIR_PointerType:$result);
+ let assemblyFormat = "attr-dict `:` qualified(type($result))";
+}
+
+def StackRestoreOp : CIR_Op<"stack_restore"> {
+ let summary = "restores the state of the function stack";
+ let description = [{
+ Restore the state of the function stack to the state it was
+ in when the corresponding cir.stack_save executed.
+ Useful for implementing language features like variable length arrays.
+
+ ```mlir
+ %0 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] {alignment = 8 : i64}
+ %1 = cir.stack_save : <!u8i>
+ cir.store %1, %0 : !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>
+ %2 = cir.load %0 : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
+ cir.stack_restore %2 : !cir.ptr<!u8i>
+ ```
+ }];
+
+ let arguments = (ins CIR_PointerType:$ptr);
+ let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))";
+
+ let llvmOp = "StackRestoreOp";
+}
+
//===----------------------------------------------------------------------===//
// UnreachableOp
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8c4a67258df3f..0673b1543d91e 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1467,6 +1467,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMConstantOpLowering,
CIRToLLVMFuncOpLowering,
CIRToLLVMGetGlobalOpLowering,
+ CIRToLLVMStackSaveOpLowering,
+ CIRToLLVMStackRestoreOpLowering,
CIRToLLVMTrapOpLowering,
CIRToLLVMUnaryOpLowering
// clang-format on
@@ -1512,6 +1514,22 @@ mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
+ cir::StackSaveOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ const mlir::Type ptrTy = getTypeConverter()->convertType(op.getType());
+ rewriter.replaceOpWithNewOp<mlir::LLVM::StackSaveOp>(op, ptrTy);
+ return mlir::success();
+}
+
+mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
+ cir::StackRestoreOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(
+ op, adaptor.getOperands().front());
+ return mlir::success();
+}
+
std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
return std::make_unique<ConvertCIRToLLVMPass>();
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 1de6c9c56b485..a7c2704e13fe6 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -242,6 +242,26 @@ class CIRToLLVMPtrStrideOpLowering
matchAndRewrite(cir::PtrStrideOp op, OpAdaptor,
mlir::ConversionPatternRewriter &) const override;
};
+
+class CIRToLLVMStackSaveOpLowering
+ : public mlir::OpConversionPattern<cir::StackSaveOp> {
+public:
+ using mlir::OpConversionPattern<cir::StackSaveOp>::OpConversionPattern;
+ mlir::LogicalResult
+ matchAndRewrite(cir::StackSaveOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &) const override;
+};
+
+class CIRToLLVMStackRestoreOpLowering
+ : public mlir::OpConversionPattern<cir::StackRestoreOp> {
+public:
+ using OpConversionPattern<cir::StackRestoreOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::StackRestoreOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override;
+};
+
} // namespace direct
} // namespace cir
diff --git a/clang/test/CIR/IR/stack-save-restore.cir b/clang/test/CIR/IR/stack-save-restore.cir
new file mode 100644
index 0000000000000..f6027258786df
--- /dev/null
+++ b/clang/test/CIR/IR/stack-save-restore.cir
@@ -0,0 +1,23 @@
+// Test the CIR operations can parse and print correctly (roundtrip)
+
+// RUN: cir-opt %s | cir-opt | FileCheck %s
+
+!u8i = !cir.int<u, 8>
+
+module {
+ cir.func @stack_save_restore() {
+ %0 = cir.stack_save : !cir.ptr<!u8i>
+ cir.stack_restore %0 : !cir.ptr<!u8i>
+ cir.return
+ }
+}
+
+//CHECK: module {
+
+//CHECK-NEXT: cir.func @stack_save_restore() {
+//CHECK-NEXT: %0 = cir.stack_save : !cir.ptr<!u8i>
+//CHECK-NEXT: cir.stack_restore %0 : !cir.ptr<!u8i>
+//CHECK-NEXT: cir.return
+//CHECK-NEXT: }
+
+//CHECK-NEXT: }
diff --git a/clang/test/CIR/Lowering/stack-save-restore.cir b/clang/test/CIR/Lowering/stack-save-restore.cir
new file mode 100644
index 0000000000000..ad9dee66b53f5
--- /dev/null
+++ b/clang/test/CIR/Lowering/stack-save-restore.cir
@@ -0,0 +1,19 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s -check-prefix=MLIR
+
+!u8i = !cir.int<u, 8>
+
+module {
+ cir.func @stack_save() {
+ %0 = cir.stack_save : !cir.ptr<!u8i>
+ cir.stack_restore %0 : !cir.ptr<!u8i>
+ cir.return
+ }
+}
+
+// MLIR: module {
+// MLIR-NEXT: llvm.func @stack_save
+// MLIR-NEXT: %0 = llvm.intr.stacksave : !llvm.ptr
+// MLIR-NEXT: llvm.intr.stackrestore %0 : !llvm.ptr
+// MLIR-NEXT: llvm.return
+// MLIR-NEXT: }
+// MLIR-NEXT: }
>From 015a2a94eae37a4138557ea6e2457c8cf394ba0c Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Mon, 21 Apr 2025 12:21:50 +0200
Subject: [PATCH 2/2] Address code review comments
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 6 ++++--
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 3 +--
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 1 +
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 2b48aac97e7ef..eaad0386852c4 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1430,6 +1430,8 @@ def StackSaveOp : CIR_Op<"stack_save"> {
that later can be passed into cir.stack_restore.
Useful for implementing language features like variable length arrays.
+ This operation is correspond to LLVM intrinsic `stacksave`.
+
```mlir
%0 = cir.stack_save : <!u8i>
```
@@ -1446,6 +1448,8 @@ def StackRestoreOp : CIR_Op<"stack_restore"> {
in when the corresponding cir.stack_save executed.
Useful for implementing language features like variable length arrays.
+ This operation is correspond to LLVM intrinsic `stackrestore`.
+
```mlir
%0 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] {alignment = 8 : i64}
%1 = cir.stack_save : <!u8i>
@@ -1457,8 +1461,6 @@ def StackRestoreOp : CIR_Op<"stack_restore"> {
let arguments = (ins CIR_PointerType:$ptr);
let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))";
-
- let llvmOp = "StackRestoreOp";
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0673b1543d91e..e0b00865f9a80 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1525,8 +1525,7 @@ mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite(
cir::StackRestoreOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
- rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(
- op, adaptor.getOperands().front());
+ rewriter.replaceOpWithNewOp<mlir::LLVM::StackRestoreOp>(op, adaptor.getPtr());
return mlir::success();
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index a7c2704e13fe6..37c73502608e7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -247,6 +247,7 @@ class CIRToLLVMStackSaveOpLowering
: public mlir::OpConversionPattern<cir::StackSaveOp> {
public:
using mlir::OpConversionPattern<cir::StackSaveOp>::OpConversionPattern;
+
mlir::LogicalResult
matchAndRewrite(cir::StackSaveOp op, OpAdaptor,
mlir::ConversionPatternRewriter &) const override;
More information about the cfe-commits
mailing list