[flang-commits] [flang] [mlir] [OpenMP] [MLIR] [Flang] Replace all uses of variables in ALLOCATE directive to use new value which is created. (PR #212361)
Raghu Maddhipatla via flang-commits
flang-commits at lists.llvm.org
Mon Jul 27 21:57:24 PDT 2026
https://github.com/raghavendhra updated https://github.com/llvm/llvm-project/pull/212361
>From a922200b820b7a1a0a74835c8d7f63724d873b7d Mon Sep 17 00:00:00 2001
From: Raghu Maddhipatla <Raghu.Maddhipatla at amd.com>
Date: Thu, 9 Jul 2026 09:39:47 -0500
Subject: [PATCH 1/5] [OpenMP] [MLIR] [Flang] Replace all uses of variables in
ALLOCATE directive to use new value which is allocated.
---
.../mlir/Target/LLVMIR/ModuleTranslation.h | 3 +++
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 11 ++++++++++
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 10 +++++++++
.../LLVMIR/openmp-allocate-directive.mlir | 22 +++++++++++++++++++
4 files changed, 46 insertions(+)
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index c5c4b105ee152..1cdecb22482de 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -100,6 +100,9 @@ class ModuleTranslation {
return valueMapping.lookup(value);
}
+ /// Remap old value with new value.
+ void remapAllValuesWith(llvm::Value *oldValue, llvm::Value *newValue);
+
/// Looks up remapped a list of remapped values.
SmallVector<llvm::Value *> lookupValues(ValueRange values);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 1c50ff192c3d5..9eb42adfd2528 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -9660,6 +9660,17 @@ convertAllocateDirOp(Operation &opInst, llvm::IRBuilderBase &builder,
}
// Record the alloc pointer keyed by the MLIR variable value.
ompIface.registerAllocatedPtr(var, allocCall);
+
+ Value baseVar = getBaseValueForTypeLookup(var);
+ if (llvm::Value *baseLlvm = moduleTranslation.lookupValue(baseVar)) {
+ llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
+ allocCall, baseLlvm->getType());
+ moduleTranslation.remapAllValuesWith(baseLlvm, boundPtr);
+ } else if (llvm::Value *varLlvm = moduleTranslation.lookupValue(var)) {
+ llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
+ allocCall, varLlvm->getType());
+ moduleTranslation.remapAllValuesWith(varLlvm, boundPtr);
+ }
}
return success();
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index b76a803f93ad9..a8e05c669c97e 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2437,6 +2437,16 @@ SmallVector<llvm::Value *> ModuleTranslation::lookupValues(ValueRange values) {
return remapped;
}
+void ModuleTranslation::remapAllValuesWith(llvm::Value *oldValue,
+ llvm::Value *newValue) {
+ if (oldValue == newValue)
+ return;
+ oldValue->replaceAllUsesWith(newValue);
+ for (auto &entry : valueMapping)
+ if (entry.second == oldValue)
+ entry.second = newValue;
+}
+
llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
if (!ompBuilder) {
ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
diff --git a/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir b/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
index d8975eb512abe..69ab9b6c00616 100644
--- a/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
@@ -115,3 +115,25 @@ llvm.func @test_allocate_array_global() {
omp.allocate_free (%z : !llvm.ptr) allocator(%alloc6 : i32)
llvm.return
}
+
+// -----
+
+// Verifies that loads and stores after omp.allocate_dir use the OMP-allocated
+// pointer rather than the original storage.
+//
+// CHECK-LABEL: define void @test_allocate_use
+// CHECK: %[[TID:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_alloc(i32 %[[TID]], i64 8, ptr null)
+// CHECK: store i32 42, ptr %[[ALLOC]]
+// CHECK: %[[VAL:.*]] = load i32, ptr %[[ALLOC]]
+// CHECK: %[[TID_FREE:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: call void @__kmpc_free(i32 %[[TID_FREE]], ptr %[[ALLOC]], ptr null)
+// CHECK: ret void
+llvm.func @test_allocate_use(%arg0: !llvm.ptr) {
+ omp.allocate_dir (%arg0 : !llvm.ptr)
+ %c42 = llvm.mlir.constant(42 : i32) : i32
+ llvm.store %c42, %arg0 : i32, !llvm.ptr
+ %v = llvm.load %arg0 : !llvm.ptr -> i32
+ omp.allocate_free (%arg0 : !llvm.ptr)
+ llvm.return
+}
>From 03e31565c428fdc4a924ae635c5e04cd450c93c3 Mon Sep 17 00:00:00 2001
From: Raghu Maddhipatla <Raghu.Maddhipatla at amd.com>
Date: Wed, 15 Jul 2026 23:38:15 -0500
Subject: [PATCH 2/5] Addressed implementation support for more test cases.
---
.../mlir/Target/LLVMIR/ModuleTranslation.h | 6 +-
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 81 +++++++++++++++----
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 54 ++++++++++++-
.../LLVMIR/openmp-allocate-directive.mlir | 52 ++++++++++++
4 files changed, 172 insertions(+), 21 deletions(-)
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 1cdecb22482de..768ed99f7c508 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -100,8 +100,10 @@ class ModuleTranslation {
return valueMapping.lookup(value);
}
- /// Remap old value with new value.
- void remapAllValuesWith(llvm::Value *oldValue, llvm::Value *newValue);
+ /// Remap old value with new value. When oldValue is a LLVM constant, builder
+ /// is used to materialize any constant-expression users as instructions.
+ void remapAllValuesWith(llvm::Value *oldValue, llvm::Value *newValue,
+ llvm::IRBuilderBase *builder = nullptr);
/// Looks up remapped a list of remapped values.
SmallVector<llvm::Value *> lookupValues(ValueRange values);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 9eb42adfd2528..ae43b97306d95 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -6289,6 +6289,64 @@ static Value getBaseValueForTypeLookup(Value value) {
return value;
}
+// Determine the LLVM type whose storage size should be allocated for an
+// OpenMP allocate directive list item. Opaque pointers lose element type, so
+// trace through declare wrappers to the underlying global or stack allocation.
+static llvm::Type *
+getAllocatedLlvmTypeForVariable(Value var,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ llvm::Type *llvmVarTy = moduleTranslation.convertType(var.getType());
+ if (!llvmVarTy->isPointerTy())
+ return llvmVarTy;
+
+ Value baseVar = getBaseValueForTypeLookup(var);
+ if (Operation *globalOp = getGlobalOpFromValue(baseVar))
+ if (auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
+ return moduleTranslation.convertType(gop.getGlobalType());
+
+ if (auto allocaOp =
+ dyn_cast_if_present<LLVM::AllocaOp>(baseVar.getDefiningOp()))
+ return moduleTranslation.convertType(allocaOp.getElemType());
+
+ if (llvm::Value *baseLlvm = moduleTranslation.lookupValue(baseVar))
+ if (auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm))
+ return allocaInst->getAllocatedType();
+
+ return llvmVarTy;
+}
+
+// For dynamically-sized stack allocations, compute the allocation size from
+// the alloca's element count at runtime.
+static std::optional<llvm::Value *>
+getDynamicAllocatedSize(Value var, LLVM::ModuleTranslation &moduleTranslation,
+ llvm::IRBuilderBase &builder,
+ const llvm::DataLayout &dataLayout) {
+ Value baseVar = getBaseValueForTypeLookup(var);
+ if (auto allocaOp =
+ dyn_cast_if_present<LLVM::AllocaOp>(baseVar.getDefiningOp())) {
+ if (Value arraySize = allocaOp.getArraySize()) {
+ llvm::Type *elemTy =
+ moduleTranslation.convertType(allocaOp.getElemType());
+ llvm::Value *numElems = moduleTranslation.lookupValue(arraySize);
+ uint64_t elemSize = dataLayout.getTypeStoreSize(elemTy).getFixedValue();
+ return builder.CreateMul(numElems, builder.getInt64(elemSize));
+ }
+ }
+ if (llvm::Value *baseLlvm = moduleTranslation.lookupValue(baseVar)) {
+ if (auto *allocaInst = dyn_cast<llvm::AllocaInst>(baseLlvm)) {
+ if (allocaInst->isArrayAllocation() &&
+ !llvm::isa<llvm::ArrayType>(allocaInst->getAllocatedType())) {
+ uint64_t elemSize =
+ dataLayout.getTypeStoreSize(allocaInst->getAllocatedType())
+ .getFixedValue();
+ return builder.CreateMul(allocaInst->getArraySize(),
+ builder.getInt64(elemSize));
+ }
+ }
+ }
+ return std::nullopt;
+}
+
static llvm::SmallString<64>
getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp,
llvm::OpenMPIRBuilder &ompBuilder,
@@ -9608,21 +9666,14 @@ convertAllocateDirOp(Operation &opInst, llvm::IRBuilderBase &builder,
}
for (Value var : vars) {
- llvm::Type *llvmVarTy = moduleTranslation.convertType(var.getType());
-
- // Opaque pointers lose element type. Trace to GlobalOp for type
- // Falls back to llvmVarTy when not from a global.
- llvm::Type *typeToInspect = llvmVarTy;
- if (llvmVarTy->isPointerTy()) {
- Value baseVar = getBaseValueForTypeLookup(var);
- if (Operation *globalOp = getGlobalOpFromValue(baseVar)) {
- if (auto gop = dyn_cast<LLVM::GlobalOp>(globalOp))
- typeToInspect = moduleTranslation.convertType(gop.getGlobalType());
- }
- }
+ llvm::Type *typeToInspect =
+ getAllocatedLlvmTypeForVariable(var, moduleTranslation);
llvm::Value *size;
- if (auto arrTy = llvm::dyn_cast<llvm::ArrayType>(typeToInspect)) {
+ if (std::optional<llvm::Value *> dynamicSize = getDynamicAllocatedSize(
+ var, moduleTranslation, builder, dataLayout)) {
+ size = *dynamicSize;
+ } else if (auto arrTy = llvm::dyn_cast<llvm::ArrayType>(typeToInspect)) {
llvm::Value *elementCount = builder.getInt64(1);
llvm::Type *currentType = arrTy;
while (auto nestedArrTy = llvm::dyn_cast<llvm::ArrayType>(currentType)) {
@@ -9665,11 +9716,11 @@ convertAllocateDirOp(Operation &opInst, llvm::IRBuilderBase &builder,
if (llvm::Value *baseLlvm = moduleTranslation.lookupValue(baseVar)) {
llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
allocCall, baseLlvm->getType());
- moduleTranslation.remapAllValuesWith(baseLlvm, boundPtr);
+ moduleTranslation.remapAllValuesWith(baseLlvm, boundPtr, &builder);
} else if (llvm::Value *varLlvm = moduleTranslation.lookupValue(var)) {
llvm::Value *boundPtr = builder.CreatePointerBitCastOrAddrSpaceCast(
allocCall, varLlvm->getType());
- moduleTranslation.remapAllValuesWith(varLlvm, boundPtr);
+ moduleTranslation.remapAllValuesWith(varLlvm, boundPtr, &builder);
}
}
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index a8e05c669c97e..94d3e1406e0bf 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -43,9 +43,11 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -2437,14 +2439,58 @@ SmallVector<llvm::Value *> ModuleTranslation::lookupValues(ValueRange values) {
return remapped;
}
+static void remapConstantPointerUses(
+ llvm::Constant *oldPtr, llvm::Value *newPtr, llvm::IRBuilderBase &builder,
+ llvm::DenseMap<llvm::Constant *, llvm::Value *> &replacements) {
+ for (llvm::Use &use : llvm::make_early_inc_range(oldPtr->uses())) {
+ if (auto *constantExpr =
+ llvm::dyn_cast<llvm::ConstantExpr>(use.getUser())) {
+ if (constantExpr->getOpcode() == llvm::Instruction::GetElementPtr) {
+ auto *gep = llvm::cast<llvm::GEPOperator>(constantExpr);
+ llvm::SmallVector<llvm::Value *, 4> indices;
+ for (unsigned i = 1, e = constantExpr->getNumOperands(); i < e; ++i)
+ indices.push_back(constantExpr->getOperand(i));
+ llvm::Value *newGEP =
+ builder.CreateGEP(gep->getSourceElementType(), newPtr, indices);
+ replacements[constantExpr] = newGEP;
+ constantExpr->replaceAllUsesWith(newGEP);
+ continue;
+ }
+ llvm::Instruction *newInst = constantExpr->getAsInstruction();
+ builder.Insert(newInst);
+ replacements[constantExpr] = newInst;
+ constantExpr->replaceAllUsesWith(newInst);
+ continue;
+ }
+ use.set(newPtr);
+ }
+}
+
void ModuleTranslation::remapAllValuesWith(llvm::Value *oldValue,
- llvm::Value *newValue) {
+ llvm::Value *newValue,
+ llvm::IRBuilderBase *builder) {
if (oldValue == newValue)
return;
- oldValue->replaceAllUsesWith(newValue);
- for (auto &entry : valueMapping)
- if (entry.second == oldValue)
+
+ llvm::DenseMap<llvm::Constant *, llvm::Value *> constantReplacements;
+ if (auto *constant = llvm::dyn_cast<llvm::Constant>(oldValue)) {
+ assert(builder &&
+ "IRBuilder required when remapping constant storage pointers");
+ remapConstantPointerUses(constant, newValue, *builder,
+ constantReplacements);
+ } else {
+ oldValue->replaceAllUsesWith(newValue);
+ }
+
+ for (auto &entry : valueMapping) {
+ if (entry.second == oldValue) {
entry.second = newValue;
+ continue;
+ }
+ if (auto *constant = llvm::dyn_cast<llvm::Constant>(entry.second))
+ if (llvm::Value *replacement = constantReplacements.lookup(constant))
+ entry.second = replacement;
+ }
}
llvm::OpenMPIRBuilder *ModuleTranslation::getOpenMPBuilder() {
diff --git a/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir b/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
index 69ab9b6c00616..9cf2894daf8a0 100644
--- a/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-allocate-directive.mlir
@@ -118,6 +118,25 @@ llvm.func @test_allocate_array_global() {
// -----
+// Verifies that array size is correctly calculated from a stack alloca:
+// [10 x i32] = 40 bytes, rounded up to alignment 64 => 64 bytes.
+//
+// CHECK-LABEL: define void @test_allocate_array_stack
+// CHECK: %[[TID:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_aligned_alloc(i32 %[[TID]], i64 64, i64 64, ptr null)
+// CHECK: %[[TID_FREE:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: call void @__kmpc_free(i32 %[[TID_FREE]], ptr %[[ALLOC]], ptr null)
+// CHECK: ret void
+llvm.func @test_allocate_array_stack() {
+ %one = llvm.mlir.constant(1 : i64) : i64
+ %arr = llvm.alloca %one x !llvm.array<10 x i32> : (i64) -> !llvm.ptr
+ omp.allocate_dir (%arr : !llvm.ptr) align(64)
+ omp.allocate_free (%arr : !llvm.ptr)
+ llvm.return
+}
+
+// -----
+
// Verifies that loads and stores after omp.allocate_dir use the OMP-allocated
// pointer rather than the original storage.
//
@@ -137,3 +156,36 @@ llvm.func @test_allocate_use(%arg0: !llvm.ptr) {
omp.allocate_free (%arg0 : !llvm.ptr)
llvm.return
}
+
+// -----
+
+// Verifies remapping when a global has multiple GEP users (COMMON block shape).
+//
+// CHECK-LABEL: define void @test_allocate_global_gep_users
+// CHECK: %[[TID:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: %[[ALLOC:.*]] = call ptr @__kmpc_alloc(i32 %[[TID]], i64 8, ptr null)
+// CHECK: %[[GEP4:.*]] = getelementptr i8, ptr %[[ALLOC]], i64 4
+// CHECK: store i32 1, ptr %[[ALLOC]], align 4
+// CHECK: store i32 2, ptr %[[GEP4]], align 4
+// CHECK: %[[TID_FREE:.*]] = call i32 @__kmpc_global_thread_num(
+// CHECK: call void @__kmpc_free(i32 %[[TID_FREE]], ptr %[[ALLOC]], ptr null)
+// CHECK: ret void
+llvm.mlir.global internal @common_like() : !llvm.array<2 x i32> {
+ %0 = llvm.mlir.zero : !llvm.array<2 x i32>
+ llvm.return %0 : !llvm.array<2 x i32>
+}
+
+llvm.func @test_allocate_global_gep_users() {
+ %base = llvm.mlir.addressof @common_like : !llvm.ptr
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %m0 = llvm.getelementptr %base[%c0, %c0] : (!llvm.ptr, i64, i64) -> !llvm.ptr, !llvm.array<2 x i32>
+ %m1 = llvm.getelementptr %base[%c0, %c1] : (!llvm.ptr, i64, i64) -> !llvm.ptr, !llvm.array<2 x i32>
+ omp.allocate_dir (%base : !llvm.ptr)
+ %one = llvm.mlir.constant(1 : i32) : i32
+ %two = llvm.mlir.constant(2 : i32) : i32
+ llvm.store %one, %m0 : i32, !llvm.ptr
+ llvm.store %two, %m1 : i32, !llvm.ptr
+ omp.allocate_free (%base : !llvm.ptr)
+ llvm.return
+}
>From 910fc5870d293f161d331dc9a54f36f6897db79d Mon Sep 17 00:00:00 2001
From: Raghu Maddhipatla <Raghu.Maddhipatla at amd.com>
Date: Mon, 27 Jul 2026 16:48:21 -0500
Subject: [PATCH 3/5] Add a TODO warning about lowering of SAVE attribute or
named COMMON block variables are not completely supported on ALLOCATE
directive.
---
flang/lib/Lower/OpenMP/OpenMP.cpp | 35 ++++++++++++++-----
.../omp-declarative-allocate-save-warning.f90 | 34 ++++++++++++++++++
2 files changed, 61 insertions(+), 8 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index b4fa431d42223..65bdf463f55bf 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2905,19 +2905,40 @@ static void genWsloopClauses(
//===----------------------------------------------------------------------===//
// Code generation functions for leaf constructs
//===----------------------------------------------------------------------===//
-static mlir::omp::AllocateDirOp genAllocateDirOp(
+
+static void genAllocateDirOp(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
lower::StatementContext &stmtCtx, lower::pft::Evaluation &eval,
mlir::Location loc, const ObjectList &objects, const ConstructQueue &queue,
ConstructQueue::const_iterator item) {
+ ObjectList supportedObjects;
+ supportedObjects.reserve(objects.size());
+ for (const Object &object : objects) {
+ const semantics::Symbol *sym = object.sym();
+ assert(sym && "Expected Symbol");
+ const semantics::Symbol &ultimate = sym->GetUltimate();
+ if (semantics::omp::IsCommonBlock(ultimate) ||
+ ultimate.attrs().test(semantics::Attr::SAVE)) {
+ mlir::emitWarning(loc,
+ "TODO : OpenMP declarative ALLOCATE on SAVE variables or "
+ "COMMON blocks is not yet supported, ignoring the ALLOCATE "
+ "directive for '" + sym->name().ToString() + "'");
+ continue;
+ }
+ supportedObjects.push_back(object);
+ }
+
+ if (supportedObjects.empty())
+ return;
+
llvm::SmallVector<mlir::Value> operandRange;
mlir::omp::AllocateDirOperands clauseOps;
- genAllocateClauses(converter, semaCtx, stmtCtx, objects, item->clauses, loc,
- operandRange, clauseOps);
+ genAllocateClauses(converter, semaCtx, stmtCtx, supportedObjects,
+ item->clauses, loc, operandRange, clauseOps);
- auto allocDirOp = mlir::omp::AllocateDirOp::create(
- converter.getFirOpBuilder(), loc, operandRange, clauseOps.align,
- clauseOps.allocator);
+ mlir::omp::AllocateDirOp::create(converter.getFirOpBuilder(), loc,
+ operandRange, clauseOps.align,
+ clauseOps.allocator);
// Register a cleanup at the Fortran scope exit.
fir::FirOpBuilder *builder = &converter.getFirOpBuilder();
@@ -2926,8 +2947,6 @@ static mlir::omp::AllocateDirOp genAllocateDirOp(
allocator]() {
mlir::omp::AllocateFreeOp::create(*builder, loc, operandRange, allocator);
});
-
- return allocDirOp;
}
static mlir::omp::BarrierOp
diff --git a/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90 b/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
new file mode 100644
index 0000000000000..f9bd360d78c36
--- /dev/null
+++ b/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
@@ -0,0 +1,34 @@
+! Verify that declarative ALLOCATE on SAVE variables or named COMMON blocks
+! emits a lowering warning and does not generate omp.allocate_dir /
+! omp.allocate_free for those variables.
+
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - 2>&1 | FileCheck %s
+
+subroutine save_allocate_warning
+ use omp_lib
+ implicit none
+ integer, save :: counter = 100
+
+ !$omp allocate(counter) allocator(omp_default_mem_alloc)
+end subroutine save_allocate_warning
+
+subroutine common_allocate_warning
+ use omp_lib
+ implicit none
+ real :: cb_a, cb_b
+ common /myblock/ cb_a, cb_b
+
+ !$omp allocate(/myblock/) allocator(omp_default_mem_alloc)
+end subroutine common_allocate_warning
+
+! Warnings are emitted during lowering before HLFIR is printed.
+! CHECK: warning: {{.*}}TODO : OpenMP declarative ALLOCATE on SAVE variables or COMMON blocks is not yet supported, ignoring the ALLOCATE directive for 'counter'
+! CHECK: warning: {{.*}}TODO : OpenMP declarative ALLOCATE on SAVE variables or COMMON blocks is not yet supported, ignoring the ALLOCATE directive for 'myblock'
+
+! CHECK-LABEL: func.func @_QPsave_allocate_warning
+! CHECK-NOT: omp.allocate_dir
+! CHECK-NOT: omp.allocate_free
+
+! CHECK-LABEL: func.func @_QPcommon_allocate_warning
+! CHECK-NOT: omp.allocate_dir
+! CHECK-NOT: omp.allocate_free
>From cf7aa2a0fa21f3056fe38ea1045de9b9c07cb505 Mon Sep 17 00:00:00 2001
From: Raghu Maddhipatla <Raghu.Maddhipatla at amd.com>
Date: Mon, 27 Jul 2026 16:52:12 -0500
Subject: [PATCH 4/5] Apply clang-format changes.
---
flang/lib/Lower/OpenMP/OpenMP.cpp | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 65bdf463f55bf..7271a9c1525a9 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2906,11 +2906,13 @@ static void genWsloopClauses(
// Code generation functions for leaf constructs
//===----------------------------------------------------------------------===//
-static void genAllocateDirOp(
- lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
- lower::StatementContext &stmtCtx, lower::pft::Evaluation &eval,
- mlir::Location loc, const ObjectList &objects, const ConstructQueue &queue,
- ConstructQueue::const_iterator item) {
+static void genAllocateDirOp(lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx,
+ lower::StatementContext &stmtCtx,
+ lower::pft::Evaluation &eval, mlir::Location loc,
+ const ObjectList &objects,
+ const ConstructQueue &queue,
+ ConstructQueue::const_iterator item) {
ObjectList supportedObjects;
supportedObjects.reserve(objects.size());
for (const Object &object : objects) {
@@ -2919,10 +2921,11 @@ static void genAllocateDirOp(
const semantics::Symbol &ultimate = sym->GetUltimate();
if (semantics::omp::IsCommonBlock(ultimate) ||
ultimate.attrs().test(semantics::Attr::SAVE)) {
- mlir::emitWarning(loc,
- "TODO : OpenMP declarative ALLOCATE on SAVE variables or "
- "COMMON blocks is not yet supported, ignoring the ALLOCATE "
- "directive for '" + sym->name().ToString() + "'");
+ mlir::emitWarning(
+ loc, "TODO : OpenMP declarative ALLOCATE on SAVE variables or "
+ "COMMON blocks is not yet supported, ignoring the ALLOCATE "
+ "directive for '" +
+ sym->name().ToString() + "'");
continue;
}
supportedObjects.push_back(object);
>From ac8e411f13fe1add4b692de77bab3a45999d3939 Mon Sep 17 00:00:00 2001
From: Raghu Maddhipatla <Raghu.Maddhipatla at amd.com>
Date: Mon, 27 Jul 2026 23:19:38 -0500
Subject: [PATCH 5/5] Fix windows build test failure.
---
.../OpenMP/omp-declarative-allocate-save-warning.f90 | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90 b/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
index f9bd360d78c36..a3b145c429395 100644
--- a/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
+++ b/flang/test/Lower/OpenMP/omp-declarative-allocate-save-warning.f90
@@ -2,23 +2,21 @@
! emits a lowering warning and does not generate omp.allocate_dir /
! omp.allocate_free for those variables.
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - 2>&1 | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - 2>&1 | FileCheck %s
subroutine save_allocate_warning
- use omp_lib
implicit none
integer, save :: counter = 100
- !$omp allocate(counter) allocator(omp_default_mem_alloc)
+ !$omp allocate(counter) allocator(1)
end subroutine save_allocate_warning
subroutine common_allocate_warning
- use omp_lib
implicit none
real :: cb_a, cb_b
common /myblock/ cb_a, cb_b
- !$omp allocate(/myblock/) allocator(omp_default_mem_alloc)
+ !$omp allocate(/myblock/) allocator(1)
end subroutine common_allocate_warning
! Warnings are emitted during lowering before HLFIR is printed.
More information about the flang-commits
mailing list