[clang] 80872d7 - [CIR] Upstream StackSave and StackRestoreOp (#136426)

via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 22 12:08:00 PDT 2025


Author: Amr Hesham
Date: 2025-04-22T21:07:57+02:00
New Revision: 80872d7a32cd335a7964df95e9fbcdee43eb1ad4

URL: https://github.com/llvm/llvm-project/commit/80872d7a32cd335a7964df95e9fbcdee43eb1ad4
DIFF: https://github.com/llvm/llvm-project/commit/80872d7a32cd335a7964df95e9fbcdee43eb1ad4.diff

LOG: [CIR] Upstream StackSave and StackRestoreOp (#136426)

This change adds support for StackSave and StackRestoreOp as a preliminary patch of VLA support

Added: 
    clang/test/CIR/IR/stack-save-restore.cir
    clang/test/CIR/Lowering/stack-save-restore.cir

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 81b447f31feca..a8fc2e755b269 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1489,6 +1489,50 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> {
     }]>];
 }
 
+//===----------------------------------------------------------------------===//
+// StackSaveOp & StackRestoreOp
+//===----------------------------------------------------------------------===//
+
+def StackSaveOp : CIR_Op<"stacksave"> {
+  let summary = "remembers the current state of the function stack";
+  let description = [{
+    Saves current state of the function stack. Returns a pointer to an opaque object
+    that later can be passed into cir.stackrestore.
+    This is used during the lowering of variable length array allocas.
+
+    This operation corresponds to LLVM intrinsic `stacksave`.
+
+    ```mlir
+    %0 = cir.stacksave : <!u8i>
+    ```
+  }];
+
+  let results = (outs CIR_PointerType:$result);
+  let assemblyFormat = "attr-dict `:` qualified(type($result))";
+}
+
+def StackRestoreOp : CIR_Op<"stackrestore"> {
+  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.stacksave executed.
+    This is used during the lowering of variable length array allocas.
+
+    This operation corresponds to LLVM intrinsic `stackrestore`.
+
+    ```mlir
+    %0 = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] {alignment = 8 : i64}
+    %1 = cir.stacksave : <!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.stackrestore %2 : !cir.ptr<!u8i>
+    ```
+  }];
+
+  let arguments = (ins CIR_PointerType:$ptr);
+  let assemblyFormat = "$ptr attr-dict `:` qualified(type($ptr))";
+}
+
 //===----------------------------------------------------------------------===//
 // UnreachableOp
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 07d57862eacc8..f25eaea05cf10 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1553,6 +1553,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMGetGlobalOpLowering,
                CIRToLLVMSelectOpLowering,
                CIRToLLVMShiftOpLowering,
+               CIRToLLVMStackSaveOpLowering,
+               CIRToLLVMStackRestoreOpLowering,
                CIRToLLVMTrapOpLowering,
                CIRToLLVMUnaryOpLowering
       // clang-format on
@@ -1598,6 +1600,21 @@ 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.getPtr());
+  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 acb872b200b55..91329523c3b0f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -262,6 +262,27 @@ 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..f98889ac1083a
--- /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.stacksave : !cir.ptr<!u8i>
+    cir.stackrestore %0 : !cir.ptr<!u8i>
+    cir.return
+  }
+}
+
+//CHECK: module  {
+
+//CHECK-NEXT: cir.func @stack_save_restore() {
+//CHECK-NEXT:   %0 = cir.stacksave : !cir.ptr<!u8i>
+//CHECK-NEXT:   cir.stackrestore %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..9e30081e3f477
--- /dev/null
+++ b/clang/test/CIR/Lowering/stack-save-restore.cir
@@ -0,0 +1,26 @@
+// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s -check-prefix=MLIR
+// RUN: cir-opt %s -cir-to-llvm -o - | mlir-translate -mlir-to-llvmir | FileCheck %s -check-prefix=LLVM
+
+!u8i = !cir.int<u, 8>
+
+module  {
+  cir.func @stack_save() {
+    %0 = cir.stacksave : !cir.ptr<!u8i>
+    cir.stackrestore %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: }
+
+// LLVM: define void @stack_save() {
+// LLVM:  %1 = call ptr @llvm.stacksave.p0()
+// LLVM:  call void @llvm.stackrestore.p0(ptr %1)
+// LLVM:  ret void
+// LLVM: }


        


More information about the cfe-commits mailing list