MLIR 22.0.0git
OpenACCUtils.cpp
Go to the documentation of this file.
1//===- OpenACCUtils.cpp ---------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
13#include "llvm/ADT/TypeSwitch.h"
14#include "llvm/Support/Casting.h"
15
17 mlir::Operation *parentOp = region.getParentOp();
18 while (parentOp) {
19 if (mlir::isa<ACC_COMPUTE_CONSTRUCT_OPS>(parentOp))
20 return parentOp;
21 parentOp = parentOp->getParentOp();
22 }
23 return nullptr;
24}
25
26template <typename OpTy>
28 auto checkIfUsedOnlyByOpInside = [&](mlir::Operation *user) {
29 // For any users which are not in the current acc region, we can ignore.
30 // Return true so that it can be used in a `all_of` check.
31 if (!region.isAncestor(user->getParentRegion()))
32 return true;
33 return mlir::isa<OpTy>(user);
34 };
35
36 return llvm::all_of(val.getUsers(), checkIfUsedOnlyByOpInside);
37}
38
43
48
49std::optional<mlir::acc::ClauseDefaultValue>
51 std::optional<mlir::acc::ClauseDefaultValue> defaultAttr;
52 Operation *currOp = op;
53
54 // Iterate outwards until a default clause is found (since OpenACC
55 // specification notes that a visible default clause is the nearest default
56 // clause appearing on the compute construct or a lexically containing data
57 // construct.
58 while (!defaultAttr.has_value() && currOp) {
59 defaultAttr =
61 std::optional<mlir::acc::ClauseDefaultValue>>(currOp)
62 .Case<ACC_COMPUTE_CONSTRUCT_OPS, mlir::acc::DataOp>(
63 [&](auto op) { return op.getDefaultAttr(); })
64 .Default([&](Operation *) { return std::nullopt; });
65 currOp = currOp->getParentOp();
66 }
67
68 return defaultAttr;
69}
70
71mlir::acc::VariableTypeCategory mlir::acc::getTypeCategory(mlir::Value var) {
72 mlir::acc::VariableTypeCategory typeCategory =
73 mlir::acc::VariableTypeCategory::uncategorized;
74 if (auto mappableTy = dyn_cast<mlir::acc::MappableType>(var.getType()))
75 typeCategory = mappableTy.getTypeCategory(var);
76 else if (auto pointerLikeTy =
77 dyn_cast<mlir::acc::PointerLikeType>(var.getType()))
78 typeCategory = pointerLikeTy.getPointeeTypeCategory(
80 pointerLikeTy.getElementType());
81 return typeCategory;
82}
83
85 Value current = v;
86
87 // Walk through view operations until a name is found or can't go further
88 while (Operation *definingOp = current.getDefiningOp()) {
89 // Check for `acc.var_name` attribute
90 if (auto varNameAttr =
91 definingOp->getAttrOfType<VarNameAttr>(getVarNameAttrName()))
92 return varNameAttr.getName().str();
93
94 // If it is a data entry operation, get name via getVarName
95 if (isa<ACC_DATA_ENTRY_OPS>(definingOp))
96 if (auto name = acc::getVarName(definingOp))
97 return name->str();
98
99 // If it's a view operation, continue to the source
100 if (auto viewOp = dyn_cast<ViewLikeOpInterface>(definingOp)) {
101 current = viewOp.getViewSource();
102 continue;
103 }
104
105 break;
106 }
107
108 return "";
109}
110
111std::string mlir::acc::getRecipeName(mlir::acc::RecipeKind kind,
112 mlir::Type type) {
113 assert(kind == mlir::acc::RecipeKind::private_recipe ||
114 kind == mlir::acc::RecipeKind::firstprivate_recipe ||
115 kind == mlir::acc::RecipeKind::reduction_recipe);
116 if (!llvm::isa<mlir::acc::PointerLikeType, mlir::acc::MappableType>(type))
117 return "";
118
119 std::string recipeName;
120 llvm::raw_string_ostream ss(recipeName);
121 ss << (kind == mlir::acc::RecipeKind::private_recipe ? "privatization_"
122 : kind == mlir::acc::RecipeKind::firstprivate_recipe
123 ? "firstprivatization_"
124 : "reduction_");
125
126 // Print the type using its dialect-defined textual format.
127 type.print(ss);
128 ss.flush();
129
130 // Replace invalid characters (anything that's not a letter, number, or
131 // period) since this needs to be a valid MLIR identifier.
132 for (char &c : recipeName) {
133 if (!std::isalnum(static_cast<unsigned char>(c)) && c != '.' && c != '_') {
134 if (c == '?')
135 c = 'U';
136 else if (c == '*')
137 c = 'Z';
138 else if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' ||
139 c == '}' || c == '<' || c == '>')
140 c = '_';
141 else
142 c = 'X';
143 }
144 }
145
146 return recipeName;
147}
148
150 if (auto partialEntityAccessOp =
151 dyn_cast<PartialEntityAccessOpInterface>(val.getDefiningOp())) {
152 if (!partialEntityAccessOp.isCompleteView())
153 return partialEntityAccessOp.getBaseEntity();
154 }
155
156 return val;
157}
static bool isOnlyUsedByOpClauses(mlir::Value val, mlir::Region &region)
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition Operation.h:234
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
bool isAncestor(Region *other)
Return true if this region is ancestor of the other region.
Definition Region.h:222
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition Region.h:200
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
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...
Definition Value.h:96
Type getType() const
Return the type of this value.
Definition Value.h:105
user_range getUsers() const
Definition Value.h:218
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
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 &region)
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.
Definition OpenACC.cpp:4695
mlir::Operation * getEnclosingComputeOp(mlir::Region &region)
Used to obtain the enclosing compute construct operation that contains the provided region.
static constexpr StringLiteral getVarNameAttrName()
Definition OpenACC.h:180
std::string getRecipeName(mlir::acc::RecipeKind kind, mlir::Type type)
Get the recipe name for a given recipe kind and type.
mlir::Value getBaseEntity(mlir::Value val)
bool isOnlyUsedByPrivateClauses(mlir::Value val, mlir::Region &region)
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.
Definition Value.h:497