Skip to content

Conversation

@razvanlupusoru
Copy link
Contributor

Some globals (e.g., fir.global) have initialization regions that may transitively reference other globals or type descriptors. Add getInitRegion() to GlobalVariableOpInterface to retrieve these regions, returning Region* (nullptr if the global uses attributes for initialization, as with memref.global).

Some globals (e.g., fir.global) have initialization regions that may
transitively reference other globals or type descriptors. Add
getInitRegion() to GlobalVariableOpInterface to retrieve these regions,
returning Region* (nullptr if the global uses attributes for
initialization, as with memref.global).
@llvmbot llvmbot added mlir flang Flang issues not falling into any other category mlir:openacc flang:fir-hlfir openacc labels Nov 25, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 25, 2025

@llvm/pr-subscribers-mlir-openacc

@llvm/pr-subscribers-openacc

Author: Razvan Lupusoru (razvanlupusoru)

Changes

Some globals (e.g., fir.global) have initialization regions that may transitively reference other globals or type descriptors. Add getInitRegion() to GlobalVariableOpInterface to retrieve these regions, returning Region* (nullptr if the global uses attributes for initialization, as with memref.global).


Full diff: https://github.com/llvm/llvm-project/pull/169569.diff

5 Files Affected:

  • (modified) flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h (+1)
  • (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp (+5)
  • (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td (+2)
  • (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+5)
  • (modified) mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp (+22)
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
index 0020e1ab21a56..d7f8f87ccb8bf 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
@@ -65,6 +65,7 @@ struct GlobalVariableModel
     : public mlir::acc::GlobalVariableOpInterface::ExternalModel<
           GlobalVariableModel, fir::GlobalOp> {
   bool isConstant(mlir::Operation *op) const;
+  mlir::Region *getInitRegion(mlir::Operation *op) const;
 };
 
 template <typename Op>
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
index 902a2ecdec35f..e4d02e93b041f 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
@@ -71,6 +71,11 @@ bool GlobalVariableModel::isConstant(mlir::Operation *op) const {
   return globalOp.getConstant().has_value();
 }
 
+mlir::Region *GlobalVariableModel::getInitRegion(mlir::Operation *op) const {
+  auto globalOp = mlir::cast<fir::GlobalOp>(op);
+  return globalOp.hasInitializationBody() ? &globalOp.getRegion() : nullptr;
+}
+
 // Helper to recursively process address-of operations in derived type
 // descriptors and collect all needed fir.globals.
 static void processAddrOfOpInDerivedTypeDescriptor(
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
index ec41826b2bbc8..d958006d58bad 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
@@ -72,6 +72,8 @@ def GlobalVariableOpInterface : OpInterface<"GlobalVariableOpInterface"> {
       "isConstant", (ins), [{
         return false;
       }]>,
+    InterfaceMethod<"Get the initialization region (returns nullptr if none)",
+      "::mlir::Region*", "getInitRegion", (ins)>,
   ];
 }
 
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 9b9d2b9e18ca6..841d1d781f1a1 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -227,6 +227,11 @@ struct MemrefGlobalVariableModel
     auto globalOp = cast<memref::GlobalOp>(op);
     return globalOp.getConstant();
   }
+
+  Region *getInitRegion(Operation *op) const {
+    // GlobalOp uses attributes for initialization, not regions
+    return nullptr;
+  }
 };
 
 /// Helper function for any of the times we need to modify an ArrayAttr based on
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
index 261f5c513ea24..7d52ef31b21ed 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
@@ -75,6 +75,28 @@ TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceConstant) {
   EXPECT_TRUE(globalVarIface.isConstant());
 }
 
+TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceInitRegion) {
+  // Test that memref::GlobalOp returns nullptr for getInitRegion()
+  // since it uses attributes for initialization, not regions
+
+  auto memrefType = MemRefType::get({10}, builder.getF32Type());
+  OwningOpRef<memref::GlobalOp> globalOp = memref::GlobalOp::create(
+      builder, loc,
+      /*sym_name=*/builder.getStringAttr("test_global"),
+      /*sym_visibility=*/builder.getStringAttr("private"),
+      /*type=*/TypeAttr::get(memrefType),
+      /*initial_value=*/Attribute(),
+      /*constant=*/UnitAttr(),
+      /*alignment=*/IntegerAttr());
+
+  auto globalVarIface =
+      dyn_cast<GlobalVariableOpInterface>(globalOp->getOperation());
+  ASSERT_TRUE(globalVarIface != nullptr);
+
+  // memref::GlobalOp doesn't have regions for initialization
+  EXPECT_EQ(globalVarIface.getInitRegion(), nullptr);
+}
+
 //===----------------------------------------------------------------------===//
 // AddressOfGlobalOpInterface Tests
 //===----------------------------------------------------------------------===//

@llvmbot
Copy link
Member

llvmbot commented Nov 25, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Razvan Lupusoru (razvanlupusoru)

Changes

Some globals (e.g., fir.global) have initialization regions that may transitively reference other globals or type descriptors. Add getInitRegion() to GlobalVariableOpInterface to retrieve these regions, returning Region* (nullptr if the global uses attributes for initialization, as with memref.global).


Full diff: https://github.com/llvm/llvm-project/pull/169569.diff

5 Files Affected:

  • (modified) flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h (+1)
  • (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp (+5)
  • (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td (+2)
  • (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+5)
  • (modified) mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp (+22)
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
index 0020e1ab21a56..d7f8f87ccb8bf 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
@@ -65,6 +65,7 @@ struct GlobalVariableModel
     : public mlir::acc::GlobalVariableOpInterface::ExternalModel<
           GlobalVariableModel, fir::GlobalOp> {
   bool isConstant(mlir::Operation *op) const;
+  mlir::Region *getInitRegion(mlir::Operation *op) const;
 };
 
 template <typename Op>
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
index 902a2ecdec35f..e4d02e93b041f 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
@@ -71,6 +71,11 @@ bool GlobalVariableModel::isConstant(mlir::Operation *op) const {
   return globalOp.getConstant().has_value();
 }
 
+mlir::Region *GlobalVariableModel::getInitRegion(mlir::Operation *op) const {
+  auto globalOp = mlir::cast<fir::GlobalOp>(op);
+  return globalOp.hasInitializationBody() ? &globalOp.getRegion() : nullptr;
+}
+
 // Helper to recursively process address-of operations in derived type
 // descriptors and collect all needed fir.globals.
 static void processAddrOfOpInDerivedTypeDescriptor(
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
index ec41826b2bbc8..d958006d58bad 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
@@ -72,6 +72,8 @@ def GlobalVariableOpInterface : OpInterface<"GlobalVariableOpInterface"> {
       "isConstant", (ins), [{
         return false;
       }]>,
+    InterfaceMethod<"Get the initialization region (returns nullptr if none)",
+      "::mlir::Region*", "getInitRegion", (ins)>,
   ];
 }
 
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 9b9d2b9e18ca6..841d1d781f1a1 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -227,6 +227,11 @@ struct MemrefGlobalVariableModel
     auto globalOp = cast<memref::GlobalOp>(op);
     return globalOp.getConstant();
   }
+
+  Region *getInitRegion(Operation *op) const {
+    // GlobalOp uses attributes for initialization, not regions
+    return nullptr;
+  }
 };
 
 /// Helper function for any of the times we need to modify an ArrayAttr based on
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
index 261f5c513ea24..7d52ef31b21ed 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
@@ -75,6 +75,28 @@ TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceConstant) {
   EXPECT_TRUE(globalVarIface.isConstant());
 }
 
+TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceInitRegion) {
+  // Test that memref::GlobalOp returns nullptr for getInitRegion()
+  // since it uses attributes for initialization, not regions
+
+  auto memrefType = MemRefType::get({10}, builder.getF32Type());
+  OwningOpRef<memref::GlobalOp> globalOp = memref::GlobalOp::create(
+      builder, loc,
+      /*sym_name=*/builder.getStringAttr("test_global"),
+      /*sym_visibility=*/builder.getStringAttr("private"),
+      /*type=*/TypeAttr::get(memrefType),
+      /*initial_value=*/Attribute(),
+      /*constant=*/UnitAttr(),
+      /*alignment=*/IntegerAttr());
+
+  auto globalVarIface =
+      dyn_cast<GlobalVariableOpInterface>(globalOp->getOperation());
+  ASSERT_TRUE(globalVarIface != nullptr);
+
+  // memref::GlobalOp doesn't have regions for initialization
+  EXPECT_EQ(globalVarIface.getInitRegion(), nullptr);
+}
+
 //===----------------------------------------------------------------------===//
 // AddressOfGlobalOpInterface Tests
 //===----------------------------------------------------------------------===//

@llvmbot
Copy link
Member

llvmbot commented Nov 25, 2025

@llvm/pr-subscribers-mlir

Author: Razvan Lupusoru (razvanlupusoru)

Changes

Some globals (e.g., fir.global) have initialization regions that may transitively reference other globals or type descriptors. Add getInitRegion() to GlobalVariableOpInterface to retrieve these regions, returning Region* (nullptr if the global uses attributes for initialization, as with memref.global).


Full diff: https://github.com/llvm/llvm-project/pull/169569.diff

5 Files Affected:

  • (modified) flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h (+1)
  • (modified) flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp (+5)
  • (modified) mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td (+2)
  • (modified) mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp (+5)
  • (modified) mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp (+22)
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
index 0020e1ab21a56..d7f8f87ccb8bf 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h
@@ -65,6 +65,7 @@ struct GlobalVariableModel
     : public mlir::acc::GlobalVariableOpInterface::ExternalModel<
           GlobalVariableModel, fir::GlobalOp> {
   bool isConstant(mlir::Operation *op) const;
+  mlir::Region *getInitRegion(mlir::Operation *op) const;
 };
 
 template <typename Op>
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
index 902a2ecdec35f..e4d02e93b041f 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.cpp
@@ -71,6 +71,11 @@ bool GlobalVariableModel::isConstant(mlir::Operation *op) const {
   return globalOp.getConstant().has_value();
 }
 
+mlir::Region *GlobalVariableModel::getInitRegion(mlir::Operation *op) const {
+  auto globalOp = mlir::cast<fir::GlobalOp>(op);
+  return globalOp.hasInitializationBody() ? &globalOp.getRegion() : nullptr;
+}
+
 // Helper to recursively process address-of operations in derived type
 // descriptors and collect all needed fir.globals.
 static void processAddrOfOpInDerivedTypeDescriptor(
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
index ec41826b2bbc8..d958006d58bad 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td
@@ -72,6 +72,8 @@ def GlobalVariableOpInterface : OpInterface<"GlobalVariableOpInterface"> {
       "isConstant", (ins), [{
         return false;
       }]>,
+    InterfaceMethod<"Get the initialization region (returns nullptr if none)",
+      "::mlir::Region*", "getInitRegion", (ins)>,
   ];
 }
 
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 9b9d2b9e18ca6..841d1d781f1a1 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -227,6 +227,11 @@ struct MemrefGlobalVariableModel
     auto globalOp = cast<memref::GlobalOp>(op);
     return globalOp.getConstant();
   }
+
+  Region *getInitRegion(Operation *op) const {
+    // GlobalOp uses attributes for initialization, not regions
+    return nullptr;
+  }
 };
 
 /// Helper function for any of the times we need to modify an ArrayAttr based on
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
index 261f5c513ea24..7d52ef31b21ed 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCOpsInterfacesTest.cpp
@@ -75,6 +75,28 @@ TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceConstant) {
   EXPECT_TRUE(globalVarIface.isConstant());
 }
 
+TEST_F(OpenACCOpsInterfacesTest, GlobalVariableOpInterfaceInitRegion) {
+  // Test that memref::GlobalOp returns nullptr for getInitRegion()
+  // since it uses attributes for initialization, not regions
+
+  auto memrefType = MemRefType::get({10}, builder.getF32Type());
+  OwningOpRef<memref::GlobalOp> globalOp = memref::GlobalOp::create(
+      builder, loc,
+      /*sym_name=*/builder.getStringAttr("test_global"),
+      /*sym_visibility=*/builder.getStringAttr("private"),
+      /*type=*/TypeAttr::get(memrefType),
+      /*initial_value=*/Attribute(),
+      /*constant=*/UnitAttr(),
+      /*alignment=*/IntegerAttr());
+
+  auto globalVarIface =
+      dyn_cast<GlobalVariableOpInterface>(globalOp->getOperation());
+  ASSERT_TRUE(globalVarIface != nullptr);
+
+  // memref::GlobalOp doesn't have regions for initialization
+  EXPECT_EQ(globalVarIface.getInitRegion(), nullptr);
+}
+
 //===----------------------------------------------------------------------===//
 // AddressOfGlobalOpInterface Tests
 //===----------------------------------------------------------------------===//

Copy link
Contributor

@clementval clementval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@razvanlupusoru razvanlupusoru merged commit 4f39a4f into llvm:main Nov 25, 2025
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:fir-hlfir flang Flang issues not falling into any other category mlir:openacc mlir openacc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants