[Mlir-commits] [mlir] [mlir][acc] Add gpu module and data layout utilities (PR #180988)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Feb 11 10:30:19 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-openacc

Author: Razvan Lupusoru (razvanlupusoru)

<details>
<summary>Changes</summary>

Add utility functions to support OpenACC code generation:
- getOrCreateGPUModule for GPU module management with configurable naming
- getDataLayout for querying data layout from operations with explicit spec or module fallback

---

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


11 Files Affected:

- (modified) mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h (+36) 
- (added) mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsCG.h (+39) 
- (added) mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsGPU.h (+44) 
- (modified) mlir/lib/Dialect/OpenACC/Analysis/CMakeLists.txt (+1) 
- (modified) mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp (+9) 
- (modified) mlir/lib/Dialect/OpenACC/Utils/CMakeLists.txt (+4) 
- (added) mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsCG.cpp (+55) 
- (added) mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsGPU.cpp (+47) 
- (modified) mlir/unittests/Dialect/OpenACC/CMakeLists.txt (+3) 
- (added) mlir/unittests/Dialect/OpenACC/OpenACCUtilsCGTest.cpp (+76) 
- (added) mlir/unittests/Dialect/OpenACC/OpenACCUtilsGPUTest.cpp (+89) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
index 31ef05c2f1743..6b68ffd4620e2 100644
--- a/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
+++ b/mlir/include/mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h
@@ -50,7 +50,9 @@
 #ifndef MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H
 #define MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H
 
+#include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/OpenACC/OpenACCUtils.h"
+#include "mlir/Dialect/OpenACC/OpenACCUtilsGPU.h"
 #include "mlir/IR/Remarks.h"
 #include "mlir/IR/Value.h"
 #include "mlir/Pass/AnalysisManager.h"
@@ -95,6 +97,10 @@ struct OpenACCSupportTraits {
 
     /// Check if a value use is legal in an OpenACC region.
     virtual bool isValidValueUse(Value v, mlir::Region &region) = 0;
+
+    /// Get or optionally create a GPU module in the given module.
+    virtual std::optional<gpu::GPUModuleOp>
+    getOrCreateGPUModule(ModuleOp mod, bool create, llvm::StringRef name) = 0;
   };
 
   /// SFINAE helpers to detect if implementation has optional methods
@@ -125,6 +131,16 @@ struct OpenACCSupportTraits {
       llvm::is_detected<emitRemark_t, ImplT, Operation *,
                         std::function<std::string()>, llvm::StringRef>;
 
+  template <typename ImplT, typename... Args>
+  using getOrCreateGPUModule_t =
+      decltype(std::declval<ImplT>().getOrCreateGPUModule(
+          std::declval<Args>()...));
+
+  template <typename ImplT>
+  using has_getOrCreateGPUModule =
+      llvm::is_detected<getOrCreateGPUModule_t, ImplT, ModuleOp, bool,
+                        llvm::StringRef>;
+
   /// This class wraps a concrete OpenACCSupport implementation and forwards
   /// interface calls to it. This provides type erasure, allowing different
   /// implementation types to be used interchangeably without inheritance.
@@ -172,6 +188,15 @@ struct OpenACCSupportTraits {
         return acc::isValidValueUse(v, region);
     }
 
+    std::optional<gpu::GPUModuleOp>
+    getOrCreateGPUModule(ModuleOp mod, bool create,
+                         llvm::StringRef name) final {
+      if constexpr (has_getOrCreateGPUModule<ImplT>::value)
+        return impl.getOrCreateGPUModule(mod, create, name);
+      else
+        return acc::getOrCreateGPUModule(mod, create, name);
+    }
+
   private:
     ImplT impl;
   };
@@ -270,6 +295,17 @@ class OpenACCSupport {
   /// \param region The MLIR region in which the legality is checked.
   bool isValidValueUse(Value v, Region &region);
 
+  /// Get or optionally create a GPU module in the given module.
+  ///
+  /// \param mod The module to search or create the GPU module in.
+  /// \param create If true (default), create the GPU module if it doesn't exist.
+  /// \param name The name for the GPU module. If empty, implementation uses its
+  ///        default name.
+  /// \return The GPU module if found or created, std::nullopt otherwise.
+  std::optional<gpu::GPUModuleOp>
+  getOrCreateGPUModule(ModuleOp mod, bool create = true,
+                       llvm::StringRef name = "");
+
   /// Signal that this analysis should always be preserved so that
   /// underlying implementation registration is not lost.
   bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) {
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsCG.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsCG.h
new file mode 100644
index 0000000000000..862fdd5b3e8f3
--- /dev/null
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsCG.h
@@ -0,0 +1,39 @@
+//===- OpenACCUtilsCG.h - OpenACC Code Generation Utilities ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utility functions for OpenACC code generation, including
+// data layout and type-related utilities.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
+#define MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
+
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include <optional>
+
+namespace mlir {
+class Operation;
+
+namespace acc {
+
+/// Get the data layout for an operation.
+///
+/// Attempts to get the data layout from the operation or its parent module.
+/// If `allowDefault` is true (default), a default data layout may be
+/// constructed when no explicit data layout spec is found.
+///
+/// \param op The operation to get the data layout for.
+/// \param allowDefault If true, allow returning a default data layout.
+/// \return The data layout if available, std::nullopt otherwise.
+std::optional<DataLayout> getDataLayout(Operation *op, bool allowDefault = true);
+
+} // namespace acc
+} // namespace mlir
+
+#endif // MLIR_DIALECT_OPENACC_OPENACCUTILSCG_H_
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsGPU.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsGPU.h
new file mode 100644
index 0000000000000..7a5fc46a21640
--- /dev/null
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCUtilsGPU.h
@@ -0,0 +1,44 @@
+//===- OpenACCUtilsGPU.h - OpenACC GPU Utilities -----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines utility functions for OpenACC that depend on the GPU
+// dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_OPENACC_OPENACCUTILSGPU_H_
+#define MLIR_DIALECT_OPENACC_OPENACCUTILSGPU_H_
+
+#include "mlir/Dialect/GPU/IR/GPUDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include <optional>
+
+namespace mlir {
+namespace acc {
+
+/// Default GPU module name used by OpenACC.
+constexpr llvm::StringLiteral kDefaultGPUModuleName = "acc_gpu_module";
+
+/// Get or create a GPU module in the given module.
+///
+/// If a GPU module with the specified name already exists, it is returned.
+/// If `create` is true and no GPU module exists, one is created.
+/// If `create` is false and no GPU module exists, std::nullopt is returned.
+///
+/// \param mod The module to search or create the GPU module in.
+/// \param create If true (default), create the GPU module if it doesn't exist.
+/// \param name The name for the GPU module. If empty, uses kDefaultGPUModuleName.
+/// \return The GPU module if found or created, std::nullopt otherwise.
+std::optional<gpu::GPUModuleOp>
+getOrCreateGPUModule(ModuleOp mod, bool create = true,
+                     llvm::StringRef name = kDefaultGPUModuleName);
+
+} // namespace acc
+} // namespace mlir
+
+#endif // MLIR_DIALECT_OPENACC_OPENACCUTILSGPU_H_
diff --git a/mlir/lib/Dialect/OpenACC/Analysis/CMakeLists.txt b/mlir/lib/Dialect/OpenACC/Analysis/CMakeLists.txt
index f305068e1b3bc..f2c13608855b9 100644
--- a/mlir/lib/Dialect/OpenACC/Analysis/CMakeLists.txt
+++ b/mlir/lib/Dialect/OpenACC/Analysis/CMakeLists.txt
@@ -5,6 +5,7 @@ add_mlir_dialect_library(MLIROpenACCAnalysis
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/OpenACC
 
   LINK_LIBS PUBLIC
+  MLIRGPUDialect
   MLIRIR
   MLIROpenACCDialect
   MLIROpenACCUtils
diff --git a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
index f204ace4609ab..3875122152194 100644
--- a/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
+++ b/mlir/lib/Dialect/OpenACC/Analysis/OpenACCSupport.cpp
@@ -12,6 +12,7 @@
 
 #include "mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h"
 #include "mlir/Dialect/OpenACC/OpenACCUtils.h"
+#include "mlir/Dialect/OpenACC/OpenACCUtilsGPU.h"
 
 namespace mlir {
 namespace acc {
@@ -63,5 +64,13 @@ bool OpenACCSupport::isValidValueUse(Value v, Region &region) {
   return acc::isValidValueUse(v, region);
 }
 
+std::optional<gpu::GPUModuleOp>
+OpenACCSupport::getOrCreateGPUModule(ModuleOp mod, bool create,
+                                     llvm::StringRef name) {
+  if (impl)
+    return impl->getOrCreateGPUModule(mod, create, name);
+  return acc::getOrCreateGPUModule(mod, create, name);
+}
+
 } // namespace acc
 } // namespace mlir
diff --git a/mlir/lib/Dialect/OpenACC/Utils/CMakeLists.txt b/mlir/lib/Dialect/OpenACC/Utils/CMakeLists.txt
index 532ba90355b44..baf248fd9b2ae 100644
--- a/mlir/lib/Dialect/OpenACC/Utils/CMakeLists.txt
+++ b/mlir/lib/Dialect/OpenACC/Utils/CMakeLists.txt
@@ -1,5 +1,7 @@
 add_mlir_dialect_library(MLIROpenACCUtils
   OpenACCUtils.cpp
+  OpenACCUtilsCG.cpp
+  OpenACCUtilsGPU.cpp
   OpenACCUtilsLoop.cpp
   OpenACCUtilsTiling.cpp
 
@@ -18,6 +20,8 @@ add_mlir_dialect_library(MLIROpenACCUtils
   LINK_LIBS PUBLIC
   MLIRArithDialect
   MLIRArithUtils
+  MLIRDataLayoutInterfaces
+  MLIRGPUDialect
   MLIROpenACCDialect
   MLIRIR
   MLIRSCFDialect
diff --git a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsCG.cpp b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsCG.cpp
new file mode 100644
index 0000000000000..5c5c453f2cae0
--- /dev/null
+++ b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsCG.cpp
@@ -0,0 +1,55 @@
+//===- OpenACCUtilsCG.cpp - OpenACC Code Generation Utilities -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements utility functions for OpenACC code generation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACCUtilsCG.h"
+#include "mlir/IR/BuiltinOps.h"
+
+namespace mlir {
+namespace acc {
+
+std::optional<DataLayout> getDataLayout(Operation *op, bool allowDefault) {
+  if (!op)
+    return std::nullopt;
+
+  // Walk up the parent chain to find the nearest operation with an explicit
+  // data layout spec. Check ModuleOp explicitly since it does not actually
+  // implement DataLayoutOpInterface as a trait (it just has the same methods).
+  Operation *current = op;
+  while (current) {
+    // Check for ModuleOp with explicit data layout spec
+    if (auto mod = llvm::dyn_cast<ModuleOp>(current)) {
+      if (mod.getDataLayoutSpec())
+        return DataLayout(mod);
+    } else if (auto dataLayoutOp =
+                   llvm::dyn_cast<DataLayoutOpInterface>(current)) {
+      // Check other DataLayoutOpInterface implementations
+      if (dataLayoutOp.getDataLayoutSpec())
+        return DataLayout(dataLayoutOp);
+    }
+    current = current->getParentOp();
+  }
+
+  // No explicit data layout found; return default if allowed
+  if (allowDefault) {
+    // Check if op itself is a ModuleOp
+    if (auto mod = llvm::dyn_cast<ModuleOp>(op))
+      return DataLayout(mod);
+    // Otherwise check parents
+    if (auto mod = op->getParentOfType<ModuleOp>())
+      return DataLayout(mod);
+  }
+
+  return std::nullopt;
+}
+
+} // namespace acc
+} // namespace mlir
diff --git a/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsGPU.cpp b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsGPU.cpp
new file mode 100644
index 0000000000000..fb1e34f514da9
--- /dev/null
+++ b/mlir/lib/Dialect/OpenACC/Utils/OpenACCUtilsGPU.cpp
@@ -0,0 +1,47 @@
+//===- OpenACCUtilsGPU.cpp - OpenACC GPU Utilities ------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements utility functions for OpenACC that depend on the GPU
+// dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACCUtilsGPU.h"
+#include "mlir/IR/SymbolTable.h"
+
+namespace mlir {
+namespace acc {
+
+std::optional<gpu::GPUModuleOp> getOrCreateGPUModule(ModuleOp mod, bool create,
+                                                     llvm::StringRef name) {
+  // Use default name if provided name is empty
+  llvm::StringRef moduleName =
+      name.empty() ? llvm::StringRef(kDefaultGPUModuleName) : name;
+
+  // Look for existing GPU module with the specified name
+  SymbolTable symTab(mod);
+  if (auto gpuMod = symTab.lookup<gpu::GPUModuleOp>(moduleName))
+    return gpuMod;
+
+  if (!create)
+    return std::nullopt;
+
+  // Create a new GPU module
+  auto *ctx = mod.getContext();
+  mod->setAttr(gpu::GPUDialect::getContainerModuleAttrName(),
+               UnitAttr::get(ctx));
+
+  OpBuilder builder(ctx);
+  auto gpuMod = gpu::GPUModuleOp::create(builder, mod.getLoc(), moduleName);
+  Block::iterator insertPt(mod.getBodyRegion().front().end());
+  symTab.insert(gpuMod, insertPt);
+  return gpuMod;
+}
+
+} // namespace acc
+} // namespace mlir
diff --git a/mlir/unittests/Dialect/OpenACC/CMakeLists.txt b/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
index 4359bae00ca21..7303ff581abc4 100644
--- a/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
+++ b/mlir/unittests/Dialect/OpenACC/CMakeLists.txt
@@ -2,6 +2,8 @@ add_mlir_unittest(MLIROpenACCTests
   OpenACCOpsTest.cpp
   OpenACCOpsInterfacesTest.cpp
   OpenACCTypeInterfacesTest.cpp
+  OpenACCUtilsCGTest.cpp
+  OpenACCUtilsGPUTest.cpp
   OpenACCUtilsTest.cpp
   OpenACCUtilsTilingTest.cpp
   OpenACCUtilsLoopTest.cpp
@@ -10,6 +12,7 @@ mlir_target_link_libraries(MLIROpenACCTests
   PRIVATE
   MLIRIR
   MLIRAffineDialect
+  MLIRDLTIDialect
   MLIRFuncDialect
   MLIRGPUDialect
   MLIRMemRefDialect
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsCGTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsCGTest.cpp
new file mode 100644
index 0000000000000..23827923e9e0f
--- /dev/null
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsCGTest.cpp
@@ -0,0 +1,76 @@
+//===- OpenACCUtilsCGTest.cpp - Unit tests for OpenACC CG utilities -------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACCUtilsCG.h"
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OwningOpRef.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+using namespace mlir::acc;
+
+//===----------------------------------------------------------------------===//
+// Test Fixture
+//===----------------------------------------------------------------------===//
+
+class OpenACCUtilsCGTest : public ::testing::Test {
+protected:
+  OpenACCUtilsCGTest() : b(&context), loc(UnknownLoc::get(&context)) {
+    context.loadDialect<acc::OpenACCDialect, DLTIDialect>();
+  }
+
+  MLIRContext context;
+  OpBuilder b;
+  Location loc;
+};
+
+//===----------------------------------------------------------------------===//
+// getDataLayout Tests
+//===----------------------------------------------------------------------===//
+
+TEST_F(OpenACCUtilsCGTest, getDataLayoutNoSpecAllowDefault) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // With allowDefault=true, should return a default DataLayout
+  auto dl = getDataLayout(module->getOperation(), /*allowDefault=*/true);
+  EXPECT_TRUE(dl.has_value());
+}
+
+TEST_F(OpenACCUtilsCGTest, getDataLayoutNoSpecDisallowDefault) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // With allowDefault=false and no spec, should return nullopt
+  auto dl = getDataLayout(module->getOperation(), /*allowDefault=*/false);
+  EXPECT_FALSE(dl.has_value());
+}
+
+TEST_F(OpenACCUtilsCGTest, getDataLayoutNullOp) {
+  // Null operation should return nullopt
+  auto dl = getDataLayout(nullptr, /*allowDefault=*/true);
+  EXPECT_FALSE(dl.has_value());
+}
+
+TEST_F(OpenACCUtilsCGTest, getDataLayoutWithSpec) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // Add a data layout spec to the module
+  auto indexEntry = DataLayoutEntryAttr::get(
+      IndexType::get(&context), b.getI32IntegerAttr(32));
+  auto spec = DataLayoutSpecAttr::get(&context, {indexEntry});
+  (*module)->setAttr(DLTIDialect::kDataLayoutAttrName, spec);
+
+  // With explicit spec, should return DataLayout regardless of allowDefault
+  auto dl1 = getDataLayout(module->getOperation(), /*allowDefault=*/false);
+  EXPECT_TRUE(dl1.has_value());
+
+  auto dl2 = getDataLayout(module->getOperation(), /*allowDefault=*/true);
+  EXPECT_TRUE(dl2.has_value());
+}
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsGPUTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsGPUTest.cpp
new file mode 100644
index 0000000000000..e9d94edde3a92
--- /dev/null
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsGPUTest.cpp
@@ -0,0 +1,89 @@
+//===- OpenACCUtilsGPUTest.cpp - Unit tests for OpenACC GPU utilities ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/OpenACC/OpenACCUtilsGPU.h"
+#include "mlir/Dialect/GPU/IR/GPUDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OwningOpRef.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+using namespace mlir::acc;
+
+//===----------------------------------------------------------------------===//
+// Test Fixture
+//===----------------------------------------------------------------------===//
+
+class OpenACCUtilsGPUTest : public ::testing::Test {
+protected:
+  OpenACCUtilsGPUTest() : b(&context), loc(UnknownLoc::get(&context)) {
+    context.loadDialect<gpu::GPUDialect>();
+  }
+
+  MLIRContext context;
+  OpBuilder b;
+  Location loc;
+};
+
+//===----------------------------------------------------------------------===//
+// getOrCreateGPUModule Tests
+//===----------------------------------------------------------------------===//
+
+TEST_F(OpenACCUtilsGPUTest, getOrCreateGPUModuleCreatesWhenMissing) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // First call should create the GPU module
+  auto gpuMod = getOrCreateGPUModule(*module, /*create=*/true);
+  ASSERT_TRUE(gpuMod.has_value());
+  EXPECT_EQ(gpuMod->getName(), kDefaultGPUModuleName);
+
+  // Module should now have the container module attribute
+  EXPECT_TRUE(
+      (*module)->hasAttr(gpu::GPUDialect::getContainerModuleAttrName()));
+}
+
+TEST_F(OpenACCUtilsGPUTest, getOrCreateGPUModuleReturnsExisting) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // Create a GPU module first
+  auto gpuMod1 = getOrCreateGPUModule(*module, /*create=*/true);
+  ASSERT_TRUE(gpuMod1.has_value());
+
+  // Second call should return the same module
+  auto gpuMod2 = getOrCreateGPUModule(*module, /*create=*/true);
+  ASSERT_TRUE(gpuMod2.has_value());
+  EXPECT_EQ(gpuMod1->getOperation(), gpuMod2->getOperation());
+}
+
+TEST_F(OpenACCUtilsGPUTest, getOrCreateGPUModuleNoCreateReturnsNullopt) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // With create=false and no existing GPU module, should return nullopt
+  auto gpuMod = getOrCreateGPUModule(*module, /*create=*/false);
+  EXPECT_FALSE(gpuMod.has_value());
+}
+
+TEST_F(OpenACCUtilsGPUTest, getOrCreateGPUModuleCustomName) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // Create with custom name
+  auto gpuMod =
+      getOrCreateGPUModule(*module, /*create=*/true, "custom_gpu_module");
+  ASSERT_TRUE(gpuMod.has_value());
+  EXPECT_EQ(gpuMod->getName(), "custom_gpu_module");
+}
+
+TEST_F(OpenACCUtilsGPUTest, getOrCreateGPUModuleEmptyNameUsesDefault) {
+  OwningOpRef<ModuleOp> module = ModuleOp::create(b, loc);
+
+  // Empty name should use default
+  auto gpuMod = getOrCreateGP...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/180988


More information about the Mlir-commits mailing list