[Mlir-commits] [mlir] 9a8c018 - [mlir][acc] add VariableInfo attribute to thread language specific information about privatized variables (#186368)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Mar 30 07:03:19 PDT 2026
Author: jeanPerier
Date: 2026-03-30T16:03:14+02:00
New Revision: 9a8c018081383f71e9f2f013dfea2fd26620aade
URL: https://github.com/llvm/llvm-project/commit/9a8c018081383f71e9f2f013dfea2fd26620aade
DIFF: https://github.com/llvm/llvm-project/commit/9a8c018081383f71e9f2f013dfea2fd26620aade.diff
LOG: [mlir][acc] add VariableInfo attribute to thread language specific information about privatized variables (#186368)
Add a new acc::VariableInfoAttr attribute that can be extended and implemented by
language dialects to carry language specific information about variables that is
not reflected into the MLIR type system and is needed in the implementation
of the init/copy/destroy APIs.
A new genPrivateVariableInfo API is added to the MappableTypeInterface to generate
such attribute from an mlir::Value for the host variable.
The use case and motivation is the Fortran OPTIONAL attribute. This patch adds
a new fir::OpenACCFortranVariableInfoAtt that implements the acc::VariableInfoAttr
to carry the OPTIONAL information around.
Added:
flang/test/Lower/OpenACC/acc-firstprivate-optional.f90
mlir/include/mlir/Dialect/OpenACC/OpenACCAttributes.td
mlir/include/mlir/Dialect/OpenACC/OpenACCVariableInfo.h
Modified:
flang/include/flang/Lower/OpenACC.h
flang/include/flang/Optimizer/Dialect/FIRAttr.h
flang/include/flang/Optimizer/Dialect/FIRAttr.td
flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
flang/lib/Lower/OpenACC.cpp
flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
mlir/include/mlir/Dialect/OpenACC/OpenACC.h
mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index 8e0f3da22ba9e..745c8686457f4 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -86,26 +86,6 @@ void genOpenACCRoutineConstruct(
AbstractConverter &, mlir::ModuleOp, mlir::func::FuncOp,
const std::vector<Fortran::semantics::OpenACCRoutineInfo> &);
-/// Get a acc.private.recipe op for the given type or create it if it does not
-/// exist yet.
-mlir::acc::PrivateRecipeOp
-createOrGetPrivateRecipe(fir::FirOpBuilder &, llvm::StringRef, mlir::Location,
- mlir::Type,
- llvm::SmallVector<mlir::Value> &dataOperationBounds);
-
-/// Get a acc.reduction.recipe op for the given type or create it if it does not
-/// exist yet.
-mlir::acc::ReductionRecipeOp
-createOrGetReductionRecipe(fir::FirOpBuilder &, llvm::StringRef, mlir::Location,
- mlir::Type, mlir::acc::ReductionOperator,
- llvm::SmallVector<mlir::Value> &dataOperationBounds);
-
-/// Get a acc.firstprivate.recipe op for the given type or create it if it does
-/// not exist yet.
-mlir::acc::FirstprivateRecipeOp createOrGetFirstprivateRecipe(
- fir::FirOpBuilder &, llvm::StringRef, mlir::Location, mlir::Type,
- llvm::SmallVector<mlir::Value> &dataOperationBounds);
-
void attachDeclarePostAllocAction(AbstractConverter &, fir::FirOpBuilder &,
const Fortran::semantics::Symbol &);
void attachDeclarePreDeallocAction(AbstractConverter &, fir::FirOpBuilder &,
diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.h b/flang/include/flang/Optimizer/Dialect/FIRAttr.h
index 06ec1f57173c3..ec6b7ff48329e 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.h
@@ -13,6 +13,7 @@
#ifndef FORTRAN_OPTIMIZER_DIALECT_FIRATTR_H
#define FORTRAN_OPTIMIZER_DIALECT_FIRATTR_H
+#include "mlir/Dialect/OpenACC/OpenACCVariableInfo.h"
#include "mlir/IR/BuiltinAttributes.h"
namespace mlir {
diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
index b23d28fdde55c..3bb1f443f3a5d 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
@@ -14,6 +14,7 @@
#define FIR_DIALECT_FIR_ATTRS
include "flang/Optimizer/Dialect/FIRDialect.td"
+include "mlir/Dialect/OpenACC/OpenACCAttributes.td"
include "mlir/IR/EnumAttr.td"
class fir_Attr<string name> : AttrDef<FIROpsDialect, name>;
@@ -262,4 +263,16 @@ def fir_UseRenameAttr : fir_Attr<"UseRename"> {
let assemblyFormat = "`<` $local_name `,` $symbol `>`";
}
+// Fortran-specific variable information for OpenACC.
+// Carries metadata that cannot be recovered from the FIR type system alone
+// and is required in the FIR implementation of OpenACC type interfaces.
+def fir_OpenACCFortranVariableInfoAttr
+ : AttrDef<FIROpsDialect, "OpenACCFortranVariableInfo",
+ [OpenACC_IsVariableInfoAttr],
+ "::mlir::acc::VariableInfoAttr"> {
+ let mnemonic = "acc_var_info";
+ let parameters = (ins "bool":$mayBeOptional);
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
#endif // FIR_DIALECT_FIR_ATTRS
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
index 9d952a6130f0e..01a1e19afd74b 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h
@@ -80,22 +80,29 @@ struct OpenACCMappableModel
mlir::acc::VariableTypeCategory getTypeCategory(mlir::Type type,
mlir::Value var) const;
+ mlir::acc::VariableInfoAttr
+ genPrivateVariableInfo(mlir::Type type,
+ mlir::TypedValue<mlir::acc::MappableType> var) const;
+
mlir::Value generatePrivateInit(mlir::Type type, mlir::OpBuilder &builder,
mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var,
llvm::StringRef varName,
mlir::ValueRange extents, mlir::Value initVal,
+ mlir::acc::VariableInfoAttr varInfo,
bool &needsDestroy) const;
bool generatePrivateDestroy(mlir::Type type, mlir::OpBuilder &builder,
mlir::Location loc, mlir::Value privatized,
- mlir::ValueRange bounds) const;
+ mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
bool generateCopy(mlir::Type type, mlir::OpBuilder &mlirBuilder,
mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> source,
mlir::TypedValue<mlir::acc::MappableType> dest,
- mlir::ValueRange bounds) const;
+ mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
bool generateCombiner(mlir::Type type, mlir::OpBuilder &mlirBuilder,
mlir::Location loc,
diff --git a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
index 360f4eb000a9e..a8b9bcf5cfd4b 100644
--- a/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
+++ b/flang/include/flang/Optimizer/OpenACC/Support/FIROpenACCUtils.h
@@ -60,7 +60,7 @@ bool areAllBoundsConstant(llvm::ArrayRef<mlir::Value> bounds);
/// \return The existing or created PrivateRecipeOp symbol
mlir::SymbolRefAttr
createOrGetPrivateRecipe(mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Type ty,
+ mlir::Value var,
llvm::SmallVector<mlir::Value> &dataBoundOps);
/// Create or get a firstprivate recipe for the given type and name.
@@ -71,7 +71,7 @@ createOrGetPrivateRecipe(mlir::OpBuilder &builder, mlir::Location loc,
/// \return The existing or created FirstprivateRecipeOp symbol
mlir::SymbolRefAttr
createOrGetFirstprivateRecipe(mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Type ty,
+ mlir::Value var,
llvm::SmallVector<mlir::Value> &dataBoundOps);
/// Create or get a reduction recipe for the given type, name and operator.
@@ -84,7 +84,7 @@ createOrGetFirstprivateRecipe(mlir::OpBuilder &builder, mlir::Location loc,
/// \return The existing or created ReductionRecipeOp symbol
mlir::SymbolRefAttr
createOrGetReductionRecipe(mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Type ty, mlir::acc::ReductionOperator op,
+ mlir::Value var, mlir::acc::ReductionOperator op,
llvm::SmallVector<mlir::Value> &dataBoundOps,
mlir::Attribute fastMathAttr = {});
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 51bc7597b5c98..2154f38dca568 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -789,11 +789,11 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
// For private/firstprivate, attach (and optionally record) the recipe.
if constexpr (std::is_same_v<Op, mlir::acc::PrivateOp>) {
mlir::SymbolRefAttr recipeAttr = fir::acc::createOrGetPrivateRecipe(
- builder, operandLocation, baseAddr.getType(), bounds);
+ builder, operandLocation, baseAddr, bounds);
op.setRecipeAttr(recipeAttr);
} else if constexpr (std::is_same_v<Op, mlir::acc::FirstprivateOp>) {
mlir::SymbolRefAttr recipeAttr = fir::acc::createOrGetFirstprivateRecipe(
- builder, operandLocation, baseAddr.getType(), bounds);
+ builder, operandLocation, baseAddr, bounds);
op.setRecipeAttr(recipeAttr);
}
}
@@ -1176,13 +1176,12 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
/*structured=*/true, /*implicit=*/false,
mlir::acc::DataClause::acc_reduction, info.addr.getType(), async,
asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true);
- mlir::Type ty = op.getAccVar().getType();
mlir::Attribute fastMathAttr;
if (builder.getFastMathFlags() != mlir::arith::FastMathFlags::none)
fastMathAttr = mlir::arith::FastMathFlagsAttr::get(
builder.getContext(), builder.getFastMathFlags());
mlir::SymbolRefAttr recipe = fir::acc::createOrGetReductionRecipe(
- builder, operandLocation, ty, mlirOp, bounds, fastMathAttr);
+ builder, operandLocation, info.addr, mlirOp, bounds, fastMathAttr);
op.setRecipeAttr(recipe);
reductionOperands.push_back(op.getAccVar());
// Track the symbol and its corresponding mlir::Value if requested so that
@@ -1427,8 +1426,8 @@ static void privatizeIv(
if (privateOp == nullptr) {
llvm::SmallVector<mlir::Value> noBounds;
- mlir::SymbolRefAttr recipe = fir::acc::createOrGetPrivateRecipe(
- builder, loc, ivValue.getType(), noBounds);
+ mlir::SymbolRefAttr recipe =
+ fir::acc::createOrGetPrivateRecipe(builder, loc, ivValue, noBounds);
std::stringstream asFortran;
asFortran << Fortran::lower::mangle::demangleName(toStringRef(sym.name()));
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
index 5d427c9aab8ab..25af35513d18d 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
@@ -542,6 +542,30 @@ template mlir::acc::VariableTypeCategory
OpenACCMappableModel<fir::PointerType>::getTypeCategory(mlir::Type type,
mlir::Value var) const;
+template <typename Ty>
+mlir::acc::VariableInfoAttr OpenACCMappableModel<Ty>::genPrivateVariableInfo(
+ mlir::Type type, mlir::TypedValue<mlir::acc::MappableType> var) const {
+ hlfir::Entity entity{var};
+ return fir::OpenACCFortranVariableInfoAttr::get(var.getContext(),
+ entity.mayBeOptional());
+}
+
+template mlir::acc::VariableInfoAttr
+OpenACCMappableModel<fir::BaseBoxType>::genPrivateVariableInfo(
+ mlir::Type type, mlir::TypedValue<mlir::acc::MappableType> var) const;
+
+template mlir::acc::VariableInfoAttr
+OpenACCMappableModel<fir::ReferenceType>::genPrivateVariableInfo(
+ mlir::Type type, mlir::TypedValue<mlir::acc::MappableType> var) const;
+
+template mlir::acc::VariableInfoAttr
+OpenACCMappableModel<fir::HeapType>::genPrivateVariableInfo(
+ mlir::Type type, mlir::TypedValue<mlir::acc::MappableType> var) const;
+
+template mlir::acc::VariableInfoAttr
+OpenACCMappableModel<fir::PointerType>::genPrivateVariableInfo(
+ mlir::Type type, mlir::TypedValue<mlir::acc::MappableType> var) const;
+
static mlir::acc::VariableTypeCategory
categorizePointee(mlir::Type pointer,
mlir::TypedValue<mlir::acc::PointerLikeType> varPtr,
@@ -717,7 +741,8 @@ template <typename Ty>
mlir::Value OpenACCMappableModel<Ty>::generatePrivateInit(
mlir::Type type, mlir::OpBuilder &mlirBuilder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
- mlir::ValueRange bounds, mlir::Value initVal, bool &needsDestroy) const {
+ mlir::ValueRange bounds, mlir::Value initVal, mlir::acc::VariableInfoAttr,
+ bool &needsDestroy) const {
mlir::ModuleOp mod = mlirBuilder.getInsertionBlock()
->getParent()
->getParentOfType<mlir::ModuleOp>();
@@ -900,31 +925,35 @@ template mlir::Value
OpenACCMappableModel<fir::BaseBoxType>::generatePrivateInit(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
- mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
+ mlir::ValueRange extents, mlir::Value initVal,
+ mlir::acc::VariableInfoAttr varInfo, bool &needsDestroy) const;
template mlir::Value
OpenACCMappableModel<fir::ReferenceType>::generatePrivateInit(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
- mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
+ mlir::ValueRange extents, mlir::Value initVal,
+ mlir::acc::VariableInfoAttr varInfo, bool &needsDestroy) const;
template mlir::Value OpenACCMappableModel<fir::HeapType>::generatePrivateInit(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
- mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
+ mlir::ValueRange extents, mlir::Value initVal,
+ mlir::acc::VariableInfoAttr varInfo, bool &needsDestroy) const;
template mlir::Value
OpenACCMappableModel<fir::PointerType>::generatePrivateInit(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> var, llvm::StringRef varName,
- mlir::ValueRange extents, mlir::Value initVal, bool &needsDestroy) const;
+ mlir::ValueRange extents, mlir::Value initVal,
+ mlir::acc::VariableInfoAttr varInfo, bool &needsDestroy) const;
template <typename Ty>
bool OpenACCMappableModel<Ty>::generateCopy(
mlir::Type type, mlir::OpBuilder &mlirBuilder, mlir::Location loc,
mlir::TypedValue<mlir::acc::MappableType> src,
- mlir::TypedValue<mlir::acc::MappableType> dest,
- mlir::ValueRange bounds) const {
+ mlir::TypedValue<mlir::acc::MappableType> dest, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const {
mlir::ModuleOp mod =
mlirBuilder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
assert(mod && "failed to retrieve parent module");
@@ -961,19 +990,23 @@ bool OpenACCMappableModel<Ty>::generateCopy(
template bool OpenACCMappableModel<fir::BaseBoxType>::generateCopy(
mlir::Type, mlir::OpBuilder &, mlir::Location,
mlir::TypedValue<mlir::acc::MappableType>,
- mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange) const;
+ mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange,
+ mlir::acc::VariableInfoAttr) const;
template bool OpenACCMappableModel<fir::ReferenceType>::generateCopy(
mlir::Type, mlir::OpBuilder &, mlir::Location,
mlir::TypedValue<mlir::acc::MappableType>,
- mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange) const;
+ mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange,
+ mlir::acc::VariableInfoAttr) const;
template bool OpenACCMappableModel<fir::PointerType>::generateCopy(
mlir::Type, mlir::OpBuilder &, mlir::Location,
mlir::TypedValue<mlir::acc::MappableType>,
- mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange) const;
+ mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange,
+ mlir::acc::VariableInfoAttr) const;
template bool OpenACCMappableModel<fir::HeapType>::generateCopy(
mlir::Type, mlir::OpBuilder &, mlir::Location,
mlir::TypedValue<mlir::acc::MappableType>,
- mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange) const;
+ mlir::TypedValue<mlir::acc::MappableType>, mlir::ValueRange,
+ mlir::acc::VariableInfoAttr) const;
template <typename Op>
static mlir::Value genLogicalCombiner(fir::FirOpBuilder &builder,
@@ -1175,7 +1208,8 @@ template bool OpenACCMappableModel<fir::HeapType>::generateCombiner(
template <typename Ty>
bool OpenACCMappableModel<Ty>::generatePrivateDestroy(
mlir::Type type, mlir::OpBuilder &mlirBuilder, mlir::Location loc,
- mlir::Value privatized, mlir::ValueRange bounds) const {
+ mlir::Value privatized, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const {
hlfir::Entity inputVar = hlfir::Entity{privatized};
mlir::ModuleOp mod =
mlirBuilder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
@@ -1210,16 +1244,20 @@ bool OpenACCMappableModel<Ty>::generatePrivateDestroy(
template bool OpenACCMappableModel<fir::BaseBoxType>::generatePrivateDestroy(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Value privatized, mlir::ValueRange bounds) const;
+ mlir::Value privatized, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
template bool OpenACCMappableModel<fir::ReferenceType>::generatePrivateDestroy(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Value privatized, mlir::ValueRange bounds) const;
+ mlir::Value privatized, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
template bool OpenACCMappableModel<fir::HeapType>::generatePrivateDestroy(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Value privatized, mlir::ValueRange bounds) const;
+ mlir::Value privatized, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
template bool OpenACCMappableModel<fir::PointerType>::generatePrivateDestroy(
mlir::Type type, mlir::OpBuilder &builder, mlir::Location loc,
- mlir::Value privatized, mlir::ValueRange bounds) const;
+ mlir::Value privatized, mlir::ValueRange bounds,
+ mlir::acc::VariableInfoAttr varInfo) const;
template <typename Ty>
mlir::Value OpenACCPointerLikeModel<Ty>::genAllocate(
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
index 3a8f548fefdf6..519978dba1afd 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
@@ -14,6 +14,7 @@
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/Complex.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Dialect/FIRType.h"
@@ -229,6 +230,7 @@ static std::string getBoundsString(llvm::ArrayRef<Value> bounds) {
}
static std::string getRecipeName(mlir::acc::RecipeKind kind, Type type,
+ mlir::acc::VariableInfoAttr varInfo,
const fir::KindMapping &kindMap,
llvm::ArrayRef<Value> bounds,
mlir::acc::ReductionOperator reductionOp =
@@ -256,19 +258,33 @@ static std::string getRecipeName(mlir::acc::RecipeKind kind, Type type,
break;
}
+ if (auto fortranVarInfo =
+ mlir::dyn_cast_if_present<fir::OpenACCFortranVariableInfoAttr>(
+ varInfo))
+ if (fortranVarInfo.getMayBeOptional())
+ prefixOS << "_optional";
+
if (!bounds.empty())
prefixOS << getBoundsString(bounds);
return fir::getTypeAsString(type, kindMap, prefixOS.str());
}
+using MappableValue = mlir::TypedValue<mlir::acc::MappableType>;
+
std::string fir::acc::getRecipeName(mlir::acc::RecipeKind kind, Type type,
Value var, llvm::ArrayRef<Value> bounds,
mlir::acc::ReductionOperator reductionOp) {
auto kindMap = var && var.getDefiningOp()
? fir::getKindMapping(var.getDefiningOp())
: fir::KindMapping(type.getContext());
- return ::getRecipeName(kind, type, kindMap, bounds, reductionOp);
+ mlir::acc::VariableInfoAttr varInfo;
+ if (var)
+ if (auto mappableTy =
+ mlir::dyn_cast<mlir::acc::MappableType>(var.getType()))
+ varInfo =
+ mappableTy.genPrivateVariableInfo(mlir::cast<MappableValue>(var));
+ return ::getRecipeName(kind, type, varInfo, kindMap, bounds, reductionOp);
}
/// Map acc::ReductionOperator to arith::AtomicRMWKind for identity value
@@ -397,8 +413,6 @@ static void addRecipeBoundsArgs(llvm::SmallVector<mlir::Value> &bounds,
}
}
-using MappableValue = mlir::TypedValue<mlir::acc::MappableType>;
-
// Generate the combiner or copy region block and block arguments and return the
// source and destination entities.
static std::pair<MappableValue, MappableValue>
@@ -420,7 +434,7 @@ genRecipeCombinerOrCopyRegion(fir::FirOpBuilder &builder, mlir::Location loc,
template <typename RecipeOp>
static RecipeOp genRecipeOp(
fir::FirOpBuilder &builder, mlir::ModuleOp mod, llvm::StringRef recipeName,
- mlir::Location loc, mlir::Type ty,
+ mlir::Location loc, mlir::Type ty, mlir::acc::VariableInfoAttr varInfo,
llvm::SmallVector<mlir::Value> &dataOperationBounds, bool allConstantBound,
mlir::acc::ReductionOperator op = mlir::acc::ReductionOperator::AccNone) {
mlir::OpBuilder modBuilder(mod.getBodyRegion());
@@ -459,13 +473,14 @@ static RecipeOp genRecipeOp(
auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
assert(mappableTy &&
"Expected that all variable types are considered mappable");
+ auto initArg = mlir::cast<MappableValue>(initBlock->getArgument(0));
bool needsDestroy = false;
llvm::SmallVector<mlir::Value> initBounds =
getRecipeBounds(builder, loc, dataOperationBounds,
initBlock->getArguments().drop_front(1));
mlir::Value retVal = mappableTy.generatePrivateInit(
- builder, loc, mlir::cast<MappableValue>(initBlock->getArgument(0)),
- initName, initBounds, initValue, needsDestroy);
+ builder, loc, initArg, initName, initBounds, initValue, varInfo,
+ needsDestroy);
mlir::acc::YieldOp::create(builder, loc, retVal);
// Create destroy region and generate destruction if requested.
if (needsDestroy) {
@@ -491,7 +506,7 @@ static RecipeOp genRecipeOp(
getRecipeBounds(builder, loc, dataOperationBounds,
destroyBlock->getArguments().drop_front(2));
[[maybe_unused]] bool success = mappableTy.generatePrivateDestroy(
- builder, loc, destroyBlock->getArgument(1), destroyBounds);
+ builder, loc, destroyBlock->getArgument(1), destroyBounds, varInfo);
assert(success && "failed to generate destroy region");
mlir::acc::TerminatorOp::create(builder, loc);
}
@@ -500,31 +515,44 @@ static RecipeOp genRecipeOp(
mlir::SymbolRefAttr
fir::acc::createOrGetPrivateRecipe(mlir::OpBuilder &mlirBuilder,
- mlir::Location loc, mlir::Type ty,
+ mlir::Location loc, mlir::Value var,
llvm::SmallVector<mlir::Value> &bounds) {
+ mlir::Type ty = var.getType();
mlir::ModuleOp mod =
mlirBuilder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
fir::FirOpBuilder builder(mlirBuilder, mod);
- std::string recipeName = ::getRecipeName(
- mlir::acc::RecipeKind::private_recipe, ty, builder.getKindMap(), bounds);
+ auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
+ assert(mappableTy &&
+ "Expected that all variable types are considered mappable");
+ mlir::acc::VariableInfoAttr varInfo =
+ mappableTy.genPrivateVariableInfo(mlir::cast<MappableValue>(var));
+ std::string recipeName =
+ ::getRecipeName(mlir::acc::RecipeKind::private_recipe, ty, varInfo,
+ builder.getKindMap(), bounds);
if (auto recipe = mod.lookupSymbol<mlir::acc::PrivateRecipeOp>(recipeName))
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
mlir::OpBuilder::InsertionGuard guard(builder);
bool allConstantBound = fir::acc::areAllBoundsConstant(bounds);
auto recipe = genRecipeOp<mlir::acc::PrivateRecipeOp>(
- builder, mod, recipeName, loc, ty, bounds, allConstantBound);
+ builder, mod, recipeName, loc, ty, varInfo, bounds, allConstantBound);
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
}
mlir::SymbolRefAttr fir::acc::createOrGetFirstprivateRecipe(
- mlir::OpBuilder &mlirBuilder, mlir::Location loc, mlir::Type ty,
+ mlir::OpBuilder &mlirBuilder, mlir::Location loc, mlir::Value var,
llvm::SmallVector<mlir::Value> &dataBoundOps) {
+ mlir::Type ty = var.getType();
mlir::ModuleOp mod =
mlirBuilder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
fir::FirOpBuilder builder(mlirBuilder, mod);
+ auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
+ assert(mappableTy &&
+ "Expected that all variable types are considered mappable");
+ mlir::acc::VariableInfoAttr varInfo =
+ mappableTy.genPrivateVariableInfo(mlir::cast<MappableValue>(var));
std::string recipeName =
- ::getRecipeName(mlir::acc::RecipeKind::firstprivate_recipe, ty,
+ ::getRecipeName(mlir::acc::RecipeKind::firstprivate_recipe, ty, varInfo,
builder.getKindMap(), dataBoundOps);
if (auto recipe =
mod.lookupSymbol<mlir::acc::FirstprivateRecipeOp>(recipeName))
@@ -533,33 +561,37 @@ mlir::SymbolRefAttr fir::acc::createOrGetFirstprivateRecipe(
mlir::OpBuilder::InsertionGuard guard(builder);
bool allConstantBound = fir::acc::areAllBoundsConstant(dataBoundOps);
auto recipe = genRecipeOp<mlir::acc::FirstprivateRecipeOp>(
- builder, mod, recipeName, loc, ty, dataBoundOps, allConstantBound);
+ builder, mod, recipeName, loc, ty, varInfo, dataBoundOps,
+ allConstantBound);
auto [source, destination] = genRecipeCombinerOrCopyRegion(
builder, loc, ty, recipe.getCopyRegion(), dataBoundOps, allConstantBound);
llvm::SmallVector<mlir::Value> copyBounds =
getRecipeBounds(builder, loc, dataBoundOps,
recipe.getCopyRegion().getArguments().drop_front(2));
- auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
- assert(mappableTy &&
- "Expected that all variable types are considered mappable");
- [[maybe_unused]] bool success =
- mappableTy.generateCopy(builder, loc, source, destination, copyBounds);
+ [[maybe_unused]] bool success = mappableTy.generateCopy(
+ builder, loc, source, destination, copyBounds, varInfo);
assert(success && "failed to generate copy");
mlir::acc::TerminatorOp::create(builder, loc);
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
}
mlir::SymbolRefAttr fir::acc::createOrGetReductionRecipe(
- mlir::OpBuilder &mlirBuilder, mlir::Location loc, mlir::Type ty,
+ mlir::OpBuilder &mlirBuilder, mlir::Location loc, mlir::Value var,
mlir::acc::ReductionOperator op,
llvm::SmallVector<mlir::Value> &dataBoundOps,
mlir::Attribute fastMathAttr) {
+ mlir::Type ty = var.getType();
mlir::ModuleOp mod =
mlirBuilder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
fir::FirOpBuilder builder(mlirBuilder, mod);
+ auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
+ assert(mappableTy &&
+ "Expected that all variable types are considered mappable");
+ mlir::acc::VariableInfoAttr varInfo =
+ mappableTy.genPrivateVariableInfo(mlir::cast<MappableValue>(var));
std::string recipeName =
- ::getRecipeName(mlir::acc::RecipeKind::reduction_recipe, ty,
+ ::getRecipeName(mlir::acc::RecipeKind::reduction_recipe, ty, varInfo,
builder.getKindMap(), dataBoundOps, op);
if (auto recipe = mod.lookupSymbol<mlir::acc::ReductionRecipeOp>(recipeName))
return mlir::SymbolRefAttr::get(builder.getContext(), recipe.getSymName());
@@ -567,7 +599,8 @@ mlir::SymbolRefAttr fir::acc::createOrGetReductionRecipe(
mlir::OpBuilder::InsertionGuard guard(builder);
bool allConstantBound = fir::acc::areAllBoundsConstant(dataBoundOps);
auto recipe = genRecipeOp<mlir::acc::ReductionRecipeOp>(
- builder, mod, recipeName, loc, ty, dataBoundOps, allConstantBound, op);
+ builder, mod, recipeName, loc, ty, varInfo, dataBoundOps,
+ allConstantBound, op);
auto [dest, source] = genRecipeCombinerOrCopyRegion(
builder, loc, ty, recipe.getCombinerRegion(), dataBoundOps,
@@ -576,9 +609,6 @@ mlir::SymbolRefAttr fir::acc::createOrGetReductionRecipe(
getRecipeBounds(builder, loc, dataBoundOps,
recipe.getCombinerRegion().getArguments().drop_front(2));
- auto mappableTy = mlir::dyn_cast<mlir::acc::MappableType>(ty);
- assert(mappableTy &&
- "Expected that all variable types are considered mappable");
[[maybe_unused]] bool success = mappableTy.generateCombiner(
builder, loc, dest, source, combinerBounds, op, fastMathAttr);
assert(success && "failed to generate combiner");
diff --git a/flang/test/Lower/OpenACC/acc-firstprivate-optional.f90 b/flang/test/Lower/OpenACC/acc-firstprivate-optional.f90
new file mode 100644
index 0000000000000..876495bebaab8
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-firstprivate-optional.f90
@@ -0,0 +1,13 @@
+! Test handling of OPTIONAL in data directives
+! RUN: %flang_fc1 -fopenacc -emit-hlfir %s -o - | FileCheck %s
+
+subroutine test(x)
+ real, optional :: x(100)
+ !$acc parallel firstprivate(x)
+ call foo(x)
+ !$acc end parallel
+end subroutine
+
+! CHECK: acc.firstprivate.recipe @firstprivatization_optional_ref_100xf32
+
+! TODO: generate conditional copy
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
index 55fc8251a9bbd..9e7a15feb2e70 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACC.h
@@ -13,6 +13,7 @@
#ifndef MLIR_DIALECT_OPENACC_OPENACC_H_
#define MLIR_DIALECT_OPENACC_OPENACC_H_
+#include "mlir/Dialect/OpenACC/OpenACCVariableInfo.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCAttributes.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCAttributes.td
new file mode 100644
index 0000000000000..f533fb42546fe
--- /dev/null
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCAttributes.td
@@ -0,0 +1,24 @@
+//===- OpenACCAttributes.td - OpenACC Attributes -----------*- tablegen -*-===//
+//
+// Part of the MLIR 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines OpenACC Attributes that can be extended by the dialects outside of
+// of OpenACC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPENACC_ATTRIBUTES
+#define OPENACC_ATTRIBUTES
+
+include "mlir/IR/AttrTypeBase.td"
+
+// Trait for attributes that carry OpenACC variable information.
+def OpenACC_IsVariableInfoAttr : NativeAttrTrait<"IsVariableInfo"> {
+ let cppNamespace = "::mlir::acc::AttributeTrait";
+}
+
+#endif // OPENACC_ATTRIBUTES
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index c8030b14e96c1..32ecaa6bc2d42 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -20,6 +20,7 @@ include "mlir/IR/BuiltinTypes.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpBase.td"
include "mlir/IR/SymbolInterfaces.td"
+include "mlir/Dialect/OpenACC/OpenACCAttributes.td"
include "mlir/Dialect/OpenACC/OpenACCBase.td"
include "mlir/Dialect/OpenACC/OpenACCOpsTypes.td"
include "mlir/Dialect/OpenACC/OpenACCOpsInterfaces.td"
@@ -1444,11 +1445,13 @@ def OpenACC_PrivateRecipeOp
/// and it must be a valid place for this operation to be inserted. The
/// `recipeName` must be a unique name to prevent "redefinition of symbol"
/// IR errors.
+ /// The `hostVar` is the original host variable from which the type and
+ /// language-specific metadata are derived.
static std::optional<PrivateRecipeOp> createAndPopulate(
::mlir::OpBuilder &builder,
::mlir::Location loc,
::llvm::StringRef recipeName,
- ::mlir::Type varType,
+ ::mlir::Value hostVar,
::llvm::StringRef varName = "",
::mlir::ValueRange bounds = {});
@@ -1569,11 +1572,13 @@ def OpenACC_FirstprivateRecipeOp
/// and it must be a valid place for this operation to be inserted. The
/// `recipeName` must be a unique name to prevent "redefinition of symbol"
/// IR errors.
+ /// The `hostVar` is the original host variable from which the type and
+ /// language-specific metadata are derived.
static std::optional<FirstprivateRecipeOp> createAndPopulate(
::mlir::OpBuilder &builder,
::mlir::Location loc,
::llvm::StringRef recipeName,
- ::mlir::Type varType,
+ ::mlir::Value hostVar,
::llvm::StringRef varName = "",
::mlir::ValueRange bounds = {});
}];
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
index 97def012990c0..3bd4e5c679659 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
@@ -354,6 +354,26 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
return ::mlir::acc::VariableTypeCategory::uncategorized;
}]
>,
+ InterfaceMethod<
+ /*description=*/[{
+ Produces a `VariableInfo` for a host variable. This enables passing
+ language-specific metadata (that is not captured in the type system)
+ to recipe code-generation helpers such as `generatePrivateInit`,
+ `generateCopy`, and `generatePrivateDestroy`.
+
+ The `var` is the host variable from which to extract information.
+ Implementations may use `getDefiningOp()` on this value.
+
+ The default implementation returns a null `VariableInfo`.
+ }],
+ /*retTy=*/"::mlir::acc::VariableInfoAttr",
+ /*methodName=*/"genPrivateVariableInfo",
+ /*args=*/(ins "::mlir::TypedValue<::mlir::acc::MappableType>":$var),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/[{
+ return ::mlir::acc::VariableInfoAttr();
+ }]
+ >,
InterfaceMethod<
/*description=*/[{
Generates the operations that would be normally placed in a recipe's
@@ -368,6 +388,10 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
The `initVal` can be empty - it is primarily needed for reductions
to ensure the variable is also initialized with appropriate value.
+ The `varInfo` carries language-specific metadata about the original
+ host variable (produced by `genPrivateVariableInfo`). Implementations
+ can `dyn_cast` to their language-specific subclass.
+
The `needsDestroy` out-parameter is set by implementations to indicate
that destruction code must be generated after the returned private
variable usages, typically in the destroy region of recipe operations
@@ -387,6 +411,7 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
"::llvm::StringRef":$varName,
"::mlir::ValueRange":$extents,
"::mlir::Value":$initVal,
+ "::mlir::acc::VariableInfoAttr":$varInfo,
"bool &":$needsDestroy),
/*methodBody=*/"",
/*defaultImplementation=*/[{
@@ -395,6 +420,12 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
>,
InterfaceMethod<
/*description=*/[{
+ Generates copy operations from one mappable variable to another.
+ Typically used to implement firstprivate initialization.
+
+ The `varInfo` carries language-specific metadata about the original
+ host variable (produced by `genPrivateVariableInfo`). Implementations
+ can `dyn_cast` to their language-specific subclass.
}],
/*retTy=*/"bool",
/*methodName=*/"generateCopy",
@@ -402,7 +433,8 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
"::mlir::Location":$loc,
"::mlir::TypedValue<::mlir::acc::MappableType>":$from,
"::mlir::TypedValue<::mlir::acc::MappableType>":$to,
- "::mlir::ValueRange":$bounds),
+ "::mlir::ValueRange":$bounds,
+ "::mlir::acc::VariableInfoAttr":$varInfo),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return false;
@@ -438,7 +470,11 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
this function should be a no-op and return `true`.
The `bounds` must be passed when only a section of the variable was
- privatized.
+ privatized.
+
+ The `varInfo` carries language-specific metadata about the original
+ host variable (produced by `genPrivateVariableInfo`). Implementations
+ can `dyn_cast` to their language-specific subclass.
Returns true if destruction was successfully generated or deemed not
necessary, false otherwise.
@@ -448,7 +484,8 @@ def OpenACC_MappableTypeInterface : TypeInterface<"MappableType"> {
/*args=*/(ins "::mlir::OpBuilder &":$builder,
"::mlir::Location":$loc,
"::mlir::Value":$privatized,
- "::mlir::ValueRange":$extents),
+ "::mlir::ValueRange":$extents,
+ "::mlir::acc::VariableInfoAttr":$varInfo),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return true;
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCVariableInfo.h b/mlir/include/mlir/Dialect/OpenACC/OpenACCVariableInfo.h
new file mode 100644
index 0000000000000..95009fdb53fb4
--- /dev/null
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCVariableInfo.h
@@ -0,0 +1,46 @@
+//===- OpenACCVariableInfo.h - OpenACC Variable Info Attr -------*- 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 the VariableInfoAttr base class and the IsVariableInfo
+// trait.
+//
+// Any dialect can define Language-specific variable metadata attribute by
+// manually attaching the IsVariableInfo trait and using VariableInfoAttr as
+// the baseCppClass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_OPENACC_OPENACCVARIABLEINFO_H
+#define MLIR_DIALECT_OPENACC_OPENACCVARIABLEINFO_H
+
+#include "mlir/IR/Attributes.h"
+
+namespace mlir {
+namespace acc {
+namespace AttributeTrait {
+/// Trait attached to attributes that are OpenACC variable info attributes.
+template <typename ConcreteType>
+struct IsVariableInfo
+ : public mlir::AttributeTrait::TraitBase<ConcreteType, IsVariableInfo> {};
+} // namespace AttributeTrait
+
+/// Base attribute class for language-specific variable information carried
+/// through the OpenACC type interface helpers.
+class VariableInfoAttr : public mlir::Attribute {
+public:
+ using Attribute::Attribute;
+
+ static bool classof(mlir::Attribute attr) {
+ return attr.hasTrait<::mlir::acc::AttributeTrait::IsVariableInfo>();
+ }
+};
+
+} // namespace acc
+} // namespace mlir
+
+#endif // MLIR_DIALECT_OPENACC_OPENACCVARIABLEINFO_H
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 0709b9ebb95aa..28138fd906d69 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -1543,10 +1543,16 @@ struct RemoveConstantIfConditionWithRegion : public OpRewritePattern<OpTy> {
/// Create and populate an init region for privatization recipes.
/// Returns success if the region is populated, failure otherwise.
/// Sets needsFree to indicate if the allocated memory requires deallocation.
+/// The `hostVar` is the original host variable used to derive
+/// language-specific metadata via `genPrivateVariableInfo`.
+/// The `varInfo` output parameter is set to the variable info produced.
static LogicalResult createInitRegion(OpBuilder &builder, Location loc,
- Region &initRegion, Type varType,
+ Region &initRegion, Value hostVar,
StringRef varName, ValueRange bounds,
- bool &needsFree) {
+ bool &needsFree,
+ acc::VariableInfoAttr &varInfo) {
+ Type varType = hostVar.getType();
+
// Create init block with arguments: original value + bounds
SmallVector<Type> argTypes{varType};
SmallVector<Location> argLocs{loc};
@@ -1568,8 +1574,10 @@ static LogicalResult createInitRegion(OpBuilder &builder, Location loc,
if (isa<MappableType>(varType)) {
auto mappableTy = cast<MappableType>(varType);
auto typedVar = cast<TypedValue<MappableType>>(blockArgVar);
+ auto typedHostVar = cast<TypedValue<MappableType>>(hostVar);
+ varInfo = mappableTy.genPrivateVariableInfo(typedHostVar);
privatizedValue = mappableTy.generatePrivateInit(
- builder, loc, typedVar, varName, bounds, {}, needsFree);
+ builder, loc, typedVar, varName, bounds, {}, varInfo, needsFree);
if (!privatizedValue)
return failure();
} else {
@@ -1635,9 +1643,12 @@ static LogicalResult createCopyRegion(OpBuilder &builder, Location loc,
/// Create and populate a destroy region for privatization recipes.
/// Returns success if the region is populated, failure otherwise.
+/// The `varInfo` carries language-specific metadata produced by
+/// `createInitRegion`.
static LogicalResult createDestroyRegion(OpBuilder &builder, Location loc,
Region &destroyRegion, Type varType,
- Value allocRes, ValueRange bounds) {
+ Value allocRes, ValueRange bounds,
+ acc::VariableInfoAttr varInfo) {
// Create destroy block with arguments: original value + privatized value +
// bounds
SmallVector<Type> destroyArgTypes{varType, varType};
@@ -1655,7 +1666,8 @@ static LogicalResult createDestroyRegion(OpBuilder &builder, Location loc,
cast<TypedValue<PointerLikeType>>(destroyBlock->getArgument(1));
if (isa<MappableType>(varType)) {
auto mappableTy = cast<MappableType>(varType);
- if (!mappableTy.generatePrivateDestroy(builder, loc, varToFree, bounds))
+ if (!mappableTy.generatePrivateDestroy(builder, loc, varToFree, bounds,
+ varInfo))
return failure();
} else {
assert(isa<PointerLikeType>(varType) && "Expected PointerLikeType");
@@ -1717,8 +1729,10 @@ LogicalResult acc::PrivateRecipeOp::verifyRegions() {
std::optional<PrivateRecipeOp>
PrivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
- StringRef recipeName, Type varType,
+ StringRef recipeName, Value hostVar,
StringRef varName, ValueRange bounds) {
+ Type varType = hostVar.getType();
+
// First, validate that we can handle this variable type
bool isMappable = isa<MappableType>(varType);
bool isPointerLike = isa<PointerLikeType>(varType);
@@ -1734,8 +1748,9 @@ PrivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
// Populate the init region
bool needsFree = false;
- if (failed(createInitRegion(builder, loc, recipe.getInitRegion(), varType,
- varName, bounds, needsFree))) {
+ acc::VariableInfoAttr varInfo;
+ if (failed(createInitRegion(builder, loc, recipe.getInitRegion(), hostVar,
+ varName, bounds, needsFree, varInfo))) {
recipe.erase();
return std::nullopt;
}
@@ -1748,7 +1763,7 @@ PrivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
Value allocRes = yieldOp.getOperand(0);
if (failed(createDestroyRegion(builder, loc, recipe.getDestroyRegion(),
- varType, allocRes, bounds))) {
+ varType, allocRes, bounds, varInfo))) {
recipe.erase();
return std::nullopt;
}
@@ -1811,8 +1826,10 @@ LogicalResult acc::FirstprivateRecipeOp::verifyRegions() {
std::optional<FirstprivateRecipeOp>
FirstprivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
- StringRef recipeName, Type varType,
+ StringRef recipeName, Value hostVar,
StringRef varName, ValueRange bounds) {
+ Type varType = hostVar.getType();
+
// First, validate that we can handle this variable type
bool isMappable = isa<MappableType>(varType);
bool isPointerLike = isa<PointerLikeType>(varType);
@@ -1828,8 +1845,9 @@ FirstprivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
// Populate the init region
bool needsFree = false;
- if (failed(createInitRegion(builder, loc, recipe.getInitRegion(), varType,
- varName, bounds, needsFree))) {
+ acc::VariableInfoAttr varInfo;
+ if (failed(createInitRegion(builder, loc, recipe.getInitRegion(), hostVar,
+ varName, bounds, needsFree, varInfo))) {
recipe.erase();
return std::nullopt;
}
@@ -1849,7 +1867,7 @@ FirstprivateRecipeOp::createAndPopulate(OpBuilder &builder, Location loc,
Value allocRes = yieldOp.getOperand(0);
if (failed(createDestroyRegion(builder, loc, recipe.getDestroyRegion(),
- varType, allocRes, bounds))) {
+ varType, allocRes, bounds, varInfo))) {
recipe.erase();
return std::nullopt;
}
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
index 3b83a25429234..95c8d1076ccb0 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCImplicitData.cpp
@@ -365,7 +365,7 @@ ACCImplicitData::generatePrivateRecipe(ModuleOp &module, Value var,
builder.setInsertionPointToStart(module.getBody());
auto recipe =
- acc::PrivateRecipeOp::createAndPopulate(builder, loc, recipeName, type);
+ acc::PrivateRecipeOp::createAndPopulate(builder, loc, recipeName, var);
if (!recipe.has_value())
return accSupport.emitNYI(loc, "implicit private"), nullptr;
return recipe.value();
@@ -390,7 +390,7 @@ ACCImplicitData::generateFirstprivateRecipe(ModuleOp &module, Value var,
builder.setInsertionPointToStart(module.getBody());
auto recipe = acc::FirstprivateRecipeOp::createAndPopulate(builder, loc,
- recipeName, type);
+ recipeName, var);
if (!recipe.has_value())
return accSupport.emitNYI(loc, "implicit firstprivate"), nullptr;
return recipe.value();
diff --git a/mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp b/mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp
index 2506ca4fc39ce..7b71f2c5f3b20 100644
--- a/mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp
+++ b/mlir/test/lib/Dialect/OpenACC/TestRecipePopulate.cpp
@@ -80,15 +80,15 @@ void TestRecipePopulatePass::runOnOperation() {
ValueRange bounds; // No bounds for memref tests
if (recipeType == "private") {
- auto recipe = PrivateRecipeOp::createAndPopulate(
- builder, loc, recipeName, var.getType(), varName, bounds);
+ auto recipe = PrivateRecipeOp::createAndPopulate(builder, loc, recipeName,
+ var, varName, bounds);
if (!recipe) {
op->emitError("Failed to create private recipe for ") << varName;
}
} else if (recipeType == "firstprivate") {
auto recipe = FirstprivateRecipeOp::createAndPopulate(
- builder, loc, recipeName, var.getType(), varName, bounds);
+ builder, loc, recipeName, var, varName, bounds);
if (!recipe) {
op->emitError("Failed to create firstprivate recipe for ") << varName;
@@ -101,7 +101,7 @@ void TestRecipePopulatePass::runOnOperation() {
std::string privName = "private_from_firstprivate_" + varName;
auto firstpriv = FirstprivateRecipeOp::createAndPopulate(
- builder, loc, firstprivName, var.getType(), varName, bounds);
+ builder, loc, firstprivName, var, varName, bounds);
if (!firstpriv) {
op->emitError("Failed to create firstprivate recipe for ") << varName;
More information about the Mlir-commits
mailing list