16#include "llvm/ADT/SetVector.h"
17#include "llvm/ADT/TypeSwitch.h"
18#include "llvm/IR/Intrinsics.h"
19#include "llvm/Support/Casting.h"
24 if (mlir::isa<ACC_COMPUTE_CONSTRUCT_OPS>(parentOp))
31template <
typename OpTy>
36 if (!region.
isAncestor(user->getParentRegion()))
38 return mlir::isa<OpTy>(user);
41 return llvm::all_of(val.
getUsers(), checkIfUsedOnlyByOpInside);
54std::optional<mlir::acc::ClauseDefaultValue>
56 std::optional<mlir::acc::ClauseDefaultValue> defaultAttr;
63 while (!defaultAttr.has_value() && currOp) {
66 std::optional<mlir::acc::ClauseDefaultValue>>(currOp)
67 .Case<ACC_COMPUTE_CONSTRUCT_OPS, mlir::acc::DataOp>(
68 [&](
auto op) {
return op.getDefaultAttr(); })
69 .Default([&](
Operation *) {
return std::nullopt; });
77 mlir::acc::VariableTypeCategory typeCategory =
78 mlir::acc::VariableTypeCategory::uncategorized;
79 if (
auto mappableTy = dyn_cast<mlir::acc::MappableType>(var.
getType()))
80 typeCategory = mappableTy.getTypeCategory(var);
81 else if (
auto pointerLikeTy =
82 dyn_cast<mlir::acc::PointerLikeType>(var.
getType()))
83 typeCategory = pointerLikeTy.getPointeeTypeCategory(
85 pointerLikeTy.getElementType());
95 if (
auto varNameAttr =
97 return varNameAttr.getName().str();
100 if (isa<ACC_DATA_ENTRY_OPS>(definingOp))
105 if (
auto viewOp = dyn_cast<ViewLikeOpInterface>(definingOp)) {
106 current = viewOp.getViewSource();
118 assert(kind == mlir::acc::RecipeKind::private_recipe ||
119 kind == mlir::acc::RecipeKind::firstprivate_recipe ||
120 kind == mlir::acc::RecipeKind::reduction_recipe);
121 if (!llvm::isa<mlir::acc::PointerLikeType, mlir::acc::MappableType>(type))
124 std::string recipeName;
125 llvm::raw_string_ostream ss(recipeName);
126 ss << (kind == mlir::acc::RecipeKind::private_recipe ?
"privatization_"
127 : kind == mlir::acc::RecipeKind::firstprivate_recipe
128 ?
"firstprivatization_"
137 for (
char &c : recipeName) {
138 if (!std::isalnum(
static_cast<unsigned char>(c)) && c !=
'.' && c !=
'_') {
143 else if (c ==
'(' || c ==
')' || c ==
'[' || c ==
']' || c ==
'{' ||
144 c ==
'}' || c ==
'<' || c ==
'>')
155 if (
auto partialEntityAccessOp =
156 dyn_cast<PartialEntityAccessOpInterface>(val.
getDefiningOp())) {
157 if (!partialEntityAccessOp.isCompleteView())
158 return partialEntityAccessOp.getBaseEntity();
165 mlir::SymbolRefAttr symbol,
176 *definingOpPtr = definingOp;
181 if (mlir::isa<mlir::acc::PrivateRecipeOp, mlir::acc::ReductionRecipeOp,
182 mlir::acc::FirstprivateRecipeOp>(definingOp))
187 mlir::dyn_cast_if_present<mlir::FunctionOpInterface>(definingOp)) {
200 func.getFunctionBody().empty() &&
func.getName().starts_with(
"llvm.") &&
201 llvm::Intrinsic::lookupIntrinsicID(
func.getName()) !=
202 llvm::Intrinsic::not_intrinsic)
215 llvm::SmallSetVector<mlir::Value, 8> dominatingDataClauses;
218 .Case<mlir::acc::ParallelOp, mlir::acc::KernelsOp, mlir::acc::SerialOp>(
220 for (
auto dataClause : op.getDataClauseOperands()) {
221 dominatingDataClauses.insert(dataClause);
228 while (currParentOp) {
229 if (mlir::isa<mlir::acc::DataOp>(currParentOp)) {
230 for (
auto dataClause : mlir::dyn_cast<mlir::acc::DataOp>(currParentOp)
231 .getDataClauseOperands()) {
232 dominatingDataClauses.insert(dataClause);
235 currParentOp = currParentOp->getParentOp();
242 return dominatingDataClauses.takeVector();
247 funcOp->walk([&](mlir::acc::DeclareEnterOp declareEnterOp) {
248 if (domInfo.
dominates(declareEnterOp.getOperation(), computeConstructOp)) {
251 for (
auto *user : declareEnterOp.getToken().getUsers())
252 if (
auto declareExit = mlir::dyn_cast<mlir::acc::DeclareExitOp>(user))
253 exits.push_back(declareExit);
257 if (!exits.empty() &&
258 llvm::all_of(exits, [&](mlir::acc::DeclareExitOp exitOp) {
259 return postDomInfo.postDominates(exitOp, computeConstructOp);
261 for (
auto dataClause : declareEnterOp.getDataClauseOperands())
262 dominatingDataClauses.insert(dataClause);
267 return dominatingDataClauses.takeVector();
static bool isOnlyUsedByOpClauses(mlir::Value val, mlir::Region ®ion)
A class for computing basic dominance information.
bool dominates(Operation *a, Operation *b) const
Return true if operation A dominates operation B, i.e.
Operation is the basic unit of execution within MLIR.
bool hasAttr(StringAttr name)
Return true if the operation has an attribute with the provided name, false otherwise.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
A class for computing basic postdominance information.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
bool isAncestor(Region *other)
Return true if this region is ancestor of the other region.
Operation * getParentOp()
Return the parent operation this region is attached to.
@ Private
The symbol is private and may only be referenced by SymbolRefAttrs local to the operations within the...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void print(raw_ostream &os) const
Print the current type.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
mlir::acc::VariableTypeCategory getTypeCategory(mlir::Value var)
Get the type category of an OpenACC variable.
std::string getVariableName(mlir::Value v)
Attempts to extract the variable name from a value by walking through view-like operations until an a...
std::optional< ClauseDefaultValue > getDefaultAttr(mlir::Operation *op)
Looks for an OpenACC default attribute on the current operation op or in a parent operation which enc...
bool isOnlyUsedByReductionClauses(mlir::Value val, mlir::Region ®ion)
Returns true if this value is only used by acc.reduction operations in the region.
std::optional< llvm::StringRef > getVarName(mlir::Operation *accOp)
Used to obtain the name from an acc operation.
static constexpr StringLiteral getRoutineInfoAttrName()
mlir::Operation * getEnclosingComputeOp(mlir::Region ®ion)
Used to obtain the enclosing compute construct operation that contains the provided region.
llvm::SmallVector< mlir::Value > getDominatingDataClauses(mlir::Operation *computeConstructOp, mlir::DominanceInfo &domInfo, mlir::PostDominanceInfo &postDomInfo)
Collects all data clauses that dominate the compute construct.
static constexpr StringLiteral getVarNameAttrName()
std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type)
Get the recipe name for a given recipe kind and type.
static constexpr StringLiteral getDeclareAttrName()
Used to obtain the attribute name for declare.
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr)
mlir::Value getBaseEntity(mlir::Value val)
bool isOnlyUsedByPrivateClauses(mlir::Value val, mlir::Region ®ion)
Returns true if this value is only used by acc.private operations in the region.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.