[Mlir-commits] [flang] [mlir] [mlir][acc] Add pass to convert acc declare ctors and dtors to LLVM (PR #217415)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Aug 19 11:00:28 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-openacc
Author: Razvan Lupusoru (razvanlupusoru)
<details>
<summary>Changes</summary>
Adds the `acc-declare-ctor-dtor-conversion` pass which converts `acc.global_ctor` and `acc.global_dtor` operations into LLVM functions and registers them in `llvm.mlir.global_ctors` and `llvm.mlir.global_dtors`.
The pass exposes a `priority` option to control when the generated functions run relative to other module initializers.
---
Full diff: https://github.com/llvm/llvm-project/pull/217415.diff
5 Files Affected:
- (added) flang/test/Fir/OpenACC/acc-declare-ctor-dtor-conversion.fir (+78)
- (modified) mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td (+25)
- (added) mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareCtorDtorConversion.cpp (+183)
- (modified) mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt (+2)
- (added) mlir/test/Dialect/OpenACC/acc-declare-ctor-dtor-conversion.mlir (+76)
``````````diff
diff --git a/flang/test/Fir/OpenACC/acc-declare-ctor-dtor-conversion.fir b/flang/test/Fir/OpenACC/acc-declare-ctor-dtor-conversion.fir
new file mode 100644
index 0000000000000..9bfde2f0a1825
--- /dev/null
+++ b/flang/test/Fir/OpenACC/acc-declare-ctor-dtor-conversion.fir
@@ -0,0 +1,78 @@
+// RUN: fir-opt %s -acc-declare-ctor-dtor-conversion -o - | FileCheck %s
+// RUN: fir-opt %s --pass-pipeline="builtin.module(acc-declare-ctor-dtor-conversion{generate-dtors=false})" -o - | FileCheck %s --check-prefix=NODTOR
+
+// Derived from:
+// module mm
+// integer, parameter :: N = 7
+// real :: arr(N)
+// !$acc declare create(arr)
+// end module
+
+// CHECK-LABEL: module
+// CHECK-NOT: acc.global_dtor
+// CHECK-NOT: acc.global_ctor
+
+// LLVM functions are created from acc constructors and destructors, then
+// registered once in llvm.mlir.global_ctors / global_dtors (merged with any
+// pre-existing entries such as the CUDA Fortran constructor).
+// CHECK: llvm.func internal @_QMmmEarr_acc_ctor()
+// CHECK: llvm.func internal @_QMmmEotherEarr_acc_ctor()
+// CHECK: llvm.func internal @_QMmmEarr_acc_dtor()
+// CHECK: llvm.func internal @_QMmmEotherEarr_acc_dtor()
+// CHECK: llvm.mlir.global_ctors ctors = [{{.*}}@_QMmmEarr_acc_ctor{{.*}}@_QMmmEotherEarr_acc_ctor], priorities = [{{.*}}102 : i32{{.*}}102 : i32], data = [{{.*}}#llvm.zero{{.*}}#llvm.zero]
+// CHECK: llvm.mlir.global_dtors dtors = [@_QMmmEarr_acc_dtor, @_QMmmEotherEarr_acc_dtor], priorities = [102 : i32, 102 : i32], data = [#llvm.zero, #llvm.zero]
+
+// NODTOR-LABEL: module
+// NODTOR-NOT: @_QMmmEarr_acc_dtor
+// NODTOR-NOT: @_QMmmEotherEarr_acc_dtor
+// NODTOR: llvm.func internal @_QMmmEarr_acc_ctor()
+// NODTOR: llvm.func internal @_QMmmEotherEarr_acc_ctor()
+// NODTOR: llvm.mlir.global_ctors ctors = [{{.*}}@_QMmmEarr_acc_ctor{{.*}}@_QMmmEotherEarr_acc_ctor], priorities = [{{.*}}102 : i32{{.*}}102 : i32], data = [{{.*}}#llvm.zero{{.*}}#llvm.zero]
+// NODTOR-NOT: @_QMmmEarr_acc_dtor
+// NODTOR-NOT: @_QMmmEotherEarr_acc_dtor
+// NODTOR-NOT: llvm.mlir.global_dtors
+
+module attributes {gpu.container_module} {
+ fir.global @_QMmmEarr {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.array<7xf32> {
+ %0 = fir.zero_bits !fir.array<7xf32>
+ fir.has_value %0 : !fir.array<7xf32>
+ }
+ fir.global @_QMmmEotherEarr {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.array<3xf32> {
+ %0 = fir.zero_bits !fir.array<3xf32>
+ fir.has_value %0 : !fir.array<3xf32>
+ }
+ acc.global_ctor @_QMmmEarr_acc_ctor {
+ %0 = fir.address_of(@_QMmmEarr) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.array<7xf32>>
+ %1 = acc.create varPtr(%0 : !fir.ref<!fir.array<7xf32>>) -> !fir.ref<!fir.array<7xf32>> {name = "arr", structured = false}
+ %2 = acc.declare_enter dataOperands(%1 : !fir.ref<!fir.array<7xf32>>)
+ acc.terminator
+ }
+ acc.global_ctor @_QMmmEotherEarr_acc_ctor {
+ %0 = fir.address_of(@_QMmmEotherEarr) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.array<3xf32>>
+ %1 = acc.create varPtr(%0 : !fir.ref<!fir.array<3xf32>>) -> !fir.ref<!fir.array<3xf32>> {name = "other_arr", structured = false}
+ %2 = acc.declare_enter dataOperands(%1 : !fir.ref<!fir.array<3xf32>>)
+ acc.terminator
+ }
+ acc.global_dtor @_QMmmEarr_acc_dtor {
+ %0 = fir.address_of(@_QMmmEarr) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.array<7xf32>>
+ %1 = acc.getdeviceptr varPtr(%0 : !fir.ref<!fir.array<7xf32>>) -> !fir.ref<!fir.array<7xf32>> {dataClause = #acc<data_clause acc_create>, name = "arr", structured = false}
+ acc.declare_exit dataOperands(%1 : !fir.ref<!fir.array<7xf32>>)
+ acc.delete accPtr(%1 : !fir.ref<!fir.array<7xf32>>) {dataClause = #acc<data_clause acc_create>, name = "arr", structured = false}
+ acc.terminator
+ }
+ acc.global_dtor @_QMmmEotherEarr_acc_dtor {
+ %0 = fir.address_of(@_QMmmEotherEarr) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.array<3xf32>>
+ %1 = acc.getdeviceptr varPtr(%0 : !fir.ref<!fir.array<3xf32>>) -> !fir.ref<!fir.array<3xf32>> {dataClause = #acc<data_clause acc_create>, name = "other_arr", structured = false}
+ acc.declare_exit dataOperands(%1 : !fir.ref<!fir.array<3xf32>>)
+ acc.delete accPtr(%1 : !fir.ref<!fir.array<3xf32>>) {dataClause = #acc<data_clause acc_create>, name = "other_arr", structured = false}
+ acc.terminator
+ }
+ func.func private @_FortranAProgramEndStatement()
+ llvm.func @_FortranACUFRegisterAllocator() attributes {sym_visibility = "private"}
+ llvm.func internal @__cudaFortranConstructor() {
+ llvm.call @_FortranACUFRegisterAllocator() : () -> ()
+ %0 = cuf.register_module @cuda_device_mod -> !llvm.ptr
+ llvm.return
+ }
+ llvm.mlir.global_ctors ctors = [@__cudaFortranConstructor], priorities = [0 : i32], data = [#llvm.zero]
+}
diff --git a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
index 441de84d08f1e..58e68f55c5010 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.td
@@ -160,6 +160,31 @@ def ACCDeclareGPUModuleInsertion : Pass<"acc-declare-gpu-module-insertion", "mli
];
}
+def ACCDeclareCtorDtorConversion
+ : Pass<"acc-declare-ctor-dtor-conversion", "mlir::ModuleOp"> {
+ let summary = "Convert OpenACC declare global constructors and destructors "
+ "to LLVM functions";
+ let description = [{
+ Converts `acc.global_ctor` into `llvm.func` entry points and registers them
+ in `llvm.mlir.global_ctors`. When enabled, similarly converts
+ `acc.global_dtor` and registers the functions in `llvm.mlir.global_dtors`;
+ otherwise, removes the destructor operations.
+
+ The ctor/dtor priority defaults to 102 so declare constructors run after
+ libacctarget init (priority 101).
+
+ Nested OpenACC operations inside the ctor/dtor regions are left unchanged
+ for later lowering.
+ }];
+ let options = [
+ Option<"priority", "priority", "int32_t", /*default=*/"102",
+ "Priority for ACC declare global constructors and destructors">,
+ Option<"generateDtors", "generate-dtors", "bool", /*default=*/"true",
+ "Generate LLVM destructor functions and register them globally">
+ ];
+ let dependentDialects = ["mlir::LLVM::LLVMDialect"];
+}
+
def ACCLegalizeSerial : Pass<"acc-legalize-serial", "mlir::func::FuncOp"> {
let summary = "Legalize OpenACC serial constructs";
let description = [{
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareCtorDtorConversion.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareCtorDtorConversion.cpp
new file mode 100644
index 0000000000000..acec4cff084fa
--- /dev/null
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareCtorDtorConversion.cpp
@@ -0,0 +1,183 @@
+//===- ACCDeclareCtorDtorConversion.cpp - Declare ctor/dtor to LLVM -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Convert ACC declare global constructors and destructors to LLVM functions
+// registered in llvm.mlir.global_ctors / llvm.mlir.global_dtors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenACC/Transforms/Passes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
+#include "mlir/Pass/Pass.h"
+
+namespace mlir {
+namespace acc {
+#define GEN_PASS_DEF_ACCDECLARECTORDTORCONVERSION
+#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
+} // namespace acc
+} // namespace mlir
+
+using namespace mlir;
+
+namespace {
+
+static void collectExistingGlobalCtors(
+ ModuleOp mod, SmallVectorImpl<Attribute> &ctors,
+ SmallVectorImpl<int32_t> &priorities, SmallVectorImpl<Attribute> &data,
+ SmallVectorImpl<LLVM::GlobalCtorsOp> &globalCtorsOps) {
+ for (auto globalCtors : mod.getOps<LLVM::GlobalCtorsOp>()) {
+ ctors.append(globalCtors.getCtors().begin(), globalCtors.getCtors().end());
+ for (Attribute attr : globalCtors.getPriorities())
+ priorities.push_back(cast<IntegerAttr>(attr).getInt());
+ data.append(globalCtors.getData().begin(), globalCtors.getData().end());
+ globalCtorsOps.push_back(globalCtors);
+ }
+}
+
+static void collectExistingGlobalDtors(
+ ModuleOp mod, SmallVectorImpl<Attribute> &dtors,
+ SmallVectorImpl<int32_t> &priorities, SmallVectorImpl<Attribute> &data,
+ SmallVectorImpl<LLVM::GlobalDtorsOp> &globalDtorsOps) {
+ for (auto globalDtors : mod.getOps<LLVM::GlobalDtorsOp>()) {
+ dtors.append(globalDtors.getDtors().begin(), globalDtors.getDtors().end());
+ for (Attribute attr : globalDtors.getPriorities())
+ priorities.push_back(cast<IntegerAttr>(attr).getInt());
+ data.append(globalDtors.getData().begin(), globalDtors.getData().end());
+ globalDtorsOps.push_back(globalDtors);
+ }
+}
+
+static void replaceGlobalCtors(ModuleOp mod, OpBuilder &builder,
+ ArrayRef<Attribute> ctors,
+ ArrayRef<int32_t> priorities,
+ ArrayRef<Attribute> data,
+ MutableArrayRef<LLVM::GlobalCtorsOp> oldOps) {
+ for (auto globalCtors : oldOps)
+ globalCtors.erase();
+ if (ctors.empty())
+ return;
+
+ builder.setInsertionPointToEnd(mod.getBody());
+ LLVM::GlobalCtorsOp::create(builder, mod.getLoc(), builder.getArrayAttr(ctors),
+ builder.getI32ArrayAttr(priorities),
+ builder.getArrayAttr(data));
+}
+
+static void replaceGlobalDtors(ModuleOp mod, OpBuilder &builder,
+ ArrayRef<Attribute> dtors,
+ ArrayRef<int32_t> priorities,
+ ArrayRef<Attribute> data,
+ MutableArrayRef<LLVM::GlobalDtorsOp> oldOps) {
+ for (auto globalDtors : oldOps)
+ globalDtors.erase();
+ if (dtors.empty())
+ return;
+
+ builder.setInsertionPointToEnd(mod.getBody());
+ LLVM::GlobalDtorsOp::create(builder, mod.getLoc(), builder.getArrayAttr(dtors),
+ builder.getI32ArrayAttr(priorities),
+ builder.getArrayAttr(data));
+}
+
+/// Create an llvm.func from an acc.global_ctor / acc.global_dtor region.
+/// Nested operations are cloned unchanged for later lowering.
+static LLVM::LLVMFuncOp createLLVMFunctionFromRegion(StringRef symName,
+ Region ®ion,
+ ModuleOp mod,
+ OpBuilder &builder) {
+ auto llvmVoidTy = LLVM::LLVMVoidType::get(mod.getContext());
+ auto funcTy =
+ LLVM::LLVMFunctionType::get(llvmVoidTy, {}, /*isVarArg=*/false);
+ builder.setInsertionPointToEnd(mod.getBody());
+ auto newFunc = LLVM::LLVMFuncOp::create(builder, mod.getLoc(), symName, funcTy,
+ LLVM::Linkage::Internal);
+
+ Block *entry = newFunc.addEntryBlock(builder);
+ builder.setInsertionPointToStart(entry);
+
+ IRMapping mapping;
+ mapping.map(region.front().getArguments(), entry->getArguments());
+
+ for (Operation &op : region.front()) {
+ Operation *clonedOp = builder.clone(op, mapping);
+ mapping.map(op.getResults(), clonedOp->getResults());
+ }
+
+ Operation *accTerm = entry->getTerminator();
+ LLVM::ReturnOp::create(builder, mod.getLoc(), ValueRange{});
+ accTerm->erase();
+
+ return newFunc;
+}
+
+struct ACCDeclareCtorDtorConversion
+ : public acc::impl::ACCDeclareCtorDtorConversionBase<
+ ACCDeclareCtorDtorConversion> {
+ using Base::Base;
+
+ void runOnOperation() override {
+ ModuleOp mod = getOperation();
+ OpBuilder builder{mod.getBodyRegion()};
+ SmallVector<Operation *> worklist;
+
+ SmallVector<Attribute, 8> allCtors;
+ SmallVector<int32_t, 8> ctorPriorities;
+ SmallVector<Attribute, 8> ctorData;
+ SmallVector<LLVM::GlobalCtorsOp, 4> globalCtorsOps;
+ collectExistingGlobalCtors(mod, allCtors, ctorPriorities, ctorData,
+ globalCtorsOps);
+ size_t existingCtorCount = allCtors.size();
+
+ SmallVector<Attribute, 8> allDtors;
+ SmallVector<int32_t, 8> dtorPriorities;
+ SmallVector<Attribute, 8> dtorData;
+ SmallVector<LLVM::GlobalDtorsOp, 4> globalDtorsOps;
+ collectExistingGlobalDtors(mod, allDtors, dtorPriorities, dtorData,
+ globalDtorsOps);
+ size_t existingDtorCount = allDtors.size();
+
+ mod.walk([&](acc::GlobalConstructorOp op) {
+ LLVM::LLVMFuncOp newCtor = createLLVMFunctionFromRegion(
+ op.getSymName(), op.getRegion(), mod, builder);
+ allCtors.push_back(
+ FlatSymbolRefAttr::get(mod.getContext(), newCtor.getSymName()));
+ ctorPriorities.push_back(priority);
+ // Null associated data: constructor always runs at load time.
+ ctorData.push_back(LLVM::ZeroAttr::get(builder.getContext()));
+ worklist.push_back(op.getOperation());
+ });
+
+ mod.walk([&](acc::GlobalDestructorOp op) {
+ if (generateDtors) {
+ LLVM::LLVMFuncOp newDtor = createLLVMFunctionFromRegion(
+ op.getSymName(), op.getRegion(), mod, builder);
+ allDtors.push_back(
+ FlatSymbolRefAttr::get(mod.getContext(), newDtor.getSymName()));
+ dtorPriorities.push_back(priority);
+ // Null associated data: destructor always runs at unload time.
+ dtorData.push_back(LLVM::ZeroAttr::get(builder.getContext()));
+ }
+ worklist.push_back(op.getOperation());
+ });
+
+ if (allCtors.size() > existingCtorCount)
+ replaceGlobalCtors(mod, builder, allCtors, ctorPriorities, ctorData,
+ globalCtorsOps);
+ if (allDtors.size() > existingDtorCount)
+ replaceGlobalDtors(mod, builder, allDtors, dtorPriorities, dtorData,
+ globalDtorsOps);
+
+ for (Operation *op : worklist)
+ op->erase();
+ }
+};
+
+} // namespace
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt b/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
index efad2b45f66ed..3fd2672e82c50 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/OpenACC/Transforms/CMakeLists.txt
@@ -4,6 +4,7 @@ add_mlir_dialect_library(MLIROpenACCTransforms
ACCComputeLowering.cpp
ACCRoutineLowering.cpp
ACCRoutineToGPUFunc.cpp
+ ACCDeclareCtorDtorConversion.cpp
ACCDeclareGPUModuleInsertion.cpp
ACCEmitRemarksLoop.cpp
ACCEmitRemarksPrivate.cpp
@@ -45,6 +46,7 @@ add_mlir_dialect_library(MLIROpenACCTransforms
MLIRGPUDialect
MLIRGPUUtils
MLIRIR
+ MLIRLLVMDialect
MLIRMemRefDialect
MLIRNVVMDialect
MLIRPass
diff --git a/mlir/test/Dialect/OpenACC/acc-declare-ctor-dtor-conversion.mlir b/mlir/test/Dialect/OpenACC/acc-declare-ctor-dtor-conversion.mlir
new file mode 100644
index 0000000000000..4768bbc602412
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/acc-declare-ctor-dtor-conversion.mlir
@@ -0,0 +1,76 @@
+// RUN: mlir-opt %s -acc-declare-ctor-dtor-conversion -split-input-file | FileCheck %s
+// RUN: mlir-opt %s --pass-pipeline="builtin.module(acc-declare-ctor-dtor-conversion{generate-dtors=false})" -split-input-file | FileCheck %s --check-prefix=NODTOR
+
+// CHECK-NOT: acc.global_ctor
+// CHECK-NOT: acc.global_dtor
+// CHECK: llvm.func internal @arr_acc_ctor()
+// CHECK: llvm.func internal @other_arr_acc_ctor()
+// CHECK: llvm.func internal @arr_acc_dtor()
+// CHECK: llvm.func internal @other_arr_acc_dtor()
+// CHECK: llvm.mlir.global_ctors ctors = [@arr_acc_ctor, @other_arr_acc_ctor], priorities = [102 : i32, 102 : i32], data = [#llvm.zero, #llvm.zero]
+// CHECK: llvm.mlir.global_dtors dtors = [@arr_acc_dtor, @other_arr_acc_dtor], priorities = [102 : i32, 102 : i32], data = [#llvm.zero, #llvm.zero]
+
+// NODTOR-NOT: @arr_acc_dtor
+// NODTOR-NOT: @other_arr_acc_dtor
+// NODTOR: llvm.func internal @arr_acc_ctor()
+// NODTOR: llvm.func internal @other_arr_acc_ctor()
+// NODTOR: llvm.mlir.global_ctors ctors = [@arr_acc_ctor, @other_arr_acc_ctor], priorities = [102 : i32, 102 : i32], data = [#llvm.zero, #llvm.zero]
+// NODTOR-NOT: llvm.mlir.global_dtors
+
+llvm.mlir.global external @arr() {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.array<7 x f32> {
+ %0 = llvm.mlir.zero : !llvm.array<7 x f32>
+ llvm.return %0 : !llvm.array<7 x f32>
+}
+llvm.mlir.global external @other_arr() {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.array<3 x f32> {
+ %0 = llvm.mlir.zero : !llvm.array<3 x f32>
+ llvm.return %0 : !llvm.array<3 x f32>
+}
+acc.global_ctor @arr_acc_ctor {
+ %0 = llvm.mlir.addressof @arr {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.ptr
+ %1 = acc.create varPtr(%0 : !llvm.ptr) varType(!llvm.array<7 x f32>) -> !llvm.ptr
+ acc.declare_enter dataOperands(%1 : !llvm.ptr)
+ acc.terminator
+}
+acc.global_ctor @other_arr_acc_ctor {
+ %0 = llvm.mlir.addressof @other_arr {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.ptr
+ %1 = acc.create varPtr(%0 : !llvm.ptr) varType(!llvm.array<3 x f32>) -> !llvm.ptr
+ acc.declare_enter dataOperands(%1 : !llvm.ptr)
+ acc.terminator
+}
+acc.global_dtor @arr_acc_dtor {
+ %0 = llvm.mlir.addressof @arr {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.ptr
+ %1 = acc.getdeviceptr varPtr(%0 : !llvm.ptr) varType(!llvm.array<7 x f32>) -> !llvm.ptr {dataClause = #acc<data_clause acc_create>}
+ acc.declare_exit dataOperands(%1 : !llvm.ptr)
+ acc.delete accPtr(%1 : !llvm.ptr)
+ acc.terminator
+}
+acc.global_dtor @other_arr_acc_dtor {
+ %0 = llvm.mlir.addressof @other_arr {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.ptr
+ %1 = acc.getdeviceptr varPtr(%0 : !llvm.ptr) varType(!llvm.array<3 x f32>) -> !llvm.ptr {dataClause = #acc<data_clause acc_create>}
+ acc.declare_exit dataOperands(%1 : !llvm.ptr)
+ acc.delete accPtr(%1 : !llvm.ptr)
+ acc.terminator
+}
+
+// -----
+
+// Merge with an existing llvm.mlir.global_ctors entry.
+
+// CHECK: llvm.func internal @existing_ctor
+// CHECK: llvm.func internal @merged_acc_ctor
+// CHECK: llvm.mlir.global_ctors ctors = [@existing_ctor, @merged_acc_ctor], priorities = [0 : i32, 102 : i32], data = [#llvm.zero, #llvm.zero]
+
+llvm.mlir.global external @merged_var() {acc.declare = #acc.declare<dataClause = acc_create>} : i32 {
+ %0 = llvm.mlir.constant(0 : i32) : i32
+ llvm.return %0 : i32
+}
+llvm.func internal @existing_ctor() {
+ llvm.return
+}
+llvm.mlir.global_ctors ctors = [@existing_ctor], priorities = [0 : i32], data = [#llvm.zero]
+acc.global_ctor @merged_acc_ctor {
+ %0 = llvm.mlir.addressof @merged_var {acc.declare = #acc.declare<dataClause = acc_create>} : !llvm.ptr
+ %1 = acc.create varPtr(%0 : !llvm.ptr) varType(i32) -> !llvm.ptr
+ acc.declare_enter dataOperands(%1 : !llvm.ptr)
+ acc.terminator
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/217415
More information about the Mlir-commits
mailing list