https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/136426
>From 91a6937c7b937daceef426c877703d4d0cfeae76 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Sat, 19 Apr 2025 14:22:45 +0200 Subject: [PATCH 1/4] [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 <am...@programmer.net> Date: Mon, 21 Apr 2025 12:21:50 +0200 Subject: [PATCH 2/4] 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; >From 88ffbd9e27fc19543e87cfae47a276d9f1945508 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Mon, 21 Apr 2025 20:16:13 +0200 Subject: [PATCH 3/4] Update stack operations names --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 18 +++++++++--------- clang/test/CIR/IR/stack-save-restore.cir | 8 ++++---- clang/test/CIR/Lowering/stack-save-restore.cir | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index eaad0386852c4..a0aa31d82d973 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1423,17 +1423,17 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { // StackSave & StackRestoreOp //===----------------------------------------------------------------------===// -def StackSaveOp : CIR_Op<"stack_save"> { +def StackSaveOp : CIR_Op<"stacksave"> { 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. + that later can be passed into cir.stackrestore. Useful for implementing language features like variable length arrays. - This operation is correspond to LLVM intrinsic `stacksave`. + This operation corresponds to LLVM intrinsic `stacksave`. ```mlir - %0 = cir.stack_save : <!u8i> + %0 = cir.stacksave : <!u8i> ``` }]; @@ -1441,21 +1441,21 @@ def StackSaveOp : CIR_Op<"stack_save"> { let assemblyFormat = "attr-dict `:` qualified(type($result))"; } -def StackRestoreOp : CIR_Op<"stack_restore"> { +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.stack_save executed. + in when the corresponding cir.stacksave executed. Useful for implementing language features like variable length arrays. - This operation is correspond to LLVM intrinsic `stackrestore`. + 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.stack_save : <!u8i> + %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.stack_restore %2 : !cir.ptr<!u8i> + cir.stackrestore %2 : !cir.ptr<!u8i> ``` }]; diff --git a/clang/test/CIR/IR/stack-save-restore.cir b/clang/test/CIR/IR/stack-save-restore.cir index f6027258786df..f98889ac1083a 100644 --- a/clang/test/CIR/IR/stack-save-restore.cir +++ b/clang/test/CIR/IR/stack-save-restore.cir @@ -6,8 +6,8 @@ module { cir.func @stack_save_restore() { - %0 = cir.stack_save : !cir.ptr<!u8i> - cir.stack_restore %0 : !cir.ptr<!u8i> + %0 = cir.stacksave : !cir.ptr<!u8i> + cir.stackrestore %0 : !cir.ptr<!u8i> cir.return } } @@ -15,8 +15,8 @@ module { //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: %0 = cir.stacksave : !cir.ptr<!u8i> +//CHECK-NEXT: cir.stackrestore %0 : !cir.ptr<!u8i> //CHECK-NEXT: cir.return //CHECK-NEXT: } diff --git a/clang/test/CIR/Lowering/stack-save-restore.cir b/clang/test/CIR/Lowering/stack-save-restore.cir index ad9dee66b53f5..10c04918d2650 100644 --- a/clang/test/CIR/Lowering/stack-save-restore.cir +++ b/clang/test/CIR/Lowering/stack-save-restore.cir @@ -4,8 +4,8 @@ module { cir.func @stack_save() { - %0 = cir.stack_save : !cir.ptr<!u8i> - cir.stack_restore %0 : !cir.ptr<!u8i> + %0 = cir.stacksave : !cir.ptr<!u8i> + cir.stackrestore %0 : !cir.ptr<!u8i> cir.return } } >From bb865d2b1ec562b544ab5667c9e9fe0a43b88c0a Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@programmer.net> Date: Mon, 21 Apr 2025 21:51:56 +0200 Subject: [PATCH 4/4] Add run line for lower to LLVM IR --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 ++++---- clang/test/CIR/Lowering/stack-save-restore.cir | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a0aa31d82d973..ffbe583fed2d3 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1420,15 +1420,15 @@ def CallOp : CIR_CallOpBase<"call", [NoRegionArguments]> { } //===----------------------------------------------------------------------===// -// StackSave & StackRestoreOp +// StackSaveOp & StackRestoreOp //===----------------------------------------------------------------------===// def StackSaveOp : CIR_Op<"stacksave"> { let summary = "remembers the current state of the function stack"; let description = [{ - Remembers the current state of the function stack. Returns a pointer + Saves current state of the function stack. Returns a pointer to an opaque object that later can be passed into cir.stackrestore. - Useful for implementing language features like variable length arrays. + This is used during the lowering of variable length array allocas. This operation corresponds to LLVM intrinsic `stacksave`. @@ -1446,7 +1446,7 @@ def StackRestoreOp : CIR_Op<"stackrestore"> { let description = [{ Restore the state of the function stack to the state it was in when the corresponding cir.stacksave executed. - Useful for implementing language features like variable length arrays. + This is used during the lowering of variable length array allocas. This operation corresponds to LLVM intrinsic `stackrestore`. diff --git a/clang/test/CIR/Lowering/stack-save-restore.cir b/clang/test/CIR/Lowering/stack-save-restore.cir index 10c04918d2650..9e30081e3f477 100644 --- a/clang/test/CIR/Lowering/stack-save-restore.cir +++ b/clang/test/CIR/Lowering/stack-save-restore.cir @@ -1,4 +1,5 @@ // 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> @@ -17,3 +18,9 @@ module { // 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: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits