18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/TypeSwitch.h"
23#define GEN_PASS_DEF_ACCEMITREMARKSDATA
24#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
28#define DEBUG_TYPE "acc-emit-remarks-data"
34static bool isStructuredDeclareEnter(acc::DeclareEnterOp op) {
35 return !op.getToken().getUsers().empty();
38static StringRef getDataClauseRemarkPrefix(
Operation *dataClauseOp) {
44 case acc::DataClause::acc_copyin:
46 case acc::DataClause::acc_copyin_readonly:
47 return "copyin(readonly:";
48 case acc::DataClause::acc_copy:
50 case acc::DataClause::acc_copyout:
52 case acc::DataClause::acc_copyout_zero:
53 return "copyout(zero:";
54 case acc::DataClause::acc_present:
56 case acc::DataClause::acc_create:
58 case acc::DataClause::acc_create_zero:
59 return "create(zero:";
60 case acc::DataClause::acc_delete:
62 case acc::DataClause::acc_attach:
64 case acc::DataClause::acc_detach:
66 case acc::DataClause::acc_no_create:
68 case acc::DataClause::acc_private:
70 case acc::DataClause::acc_firstprivate:
71 return "firstprivate(";
72 case acc::DataClause::acc_deviceptr:
74 case acc::DataClause::acc_update_host:
75 return "update_host(";
76 case acc::DataClause::acc_update_self:
77 return "update_self(";
78 case acc::DataClause::acc_update_device:
79 return "update_device(";
80 case acc::DataClause::acc_use_device:
82 case acc::DataClause::acc_reduction:
83 return isa<acc::CopyinOp>(dataClauseOp) ?
"copy(" :
"reduction(";
84 case acc::DataClause::acc_declare_device_resident:
85 return "device_resident(";
86 case acc::DataClause::acc_declare_link:
88 case acc::DataClause::acc_cache:
90 case acc::DataClause::acc_cache_readonly:
91 return "cache(readonly:";
92 case acc::DataClause::acc_getdeviceptr:
95 llvm_unreachable(
"Unhandled data clause");
99 std::string &varName) {
100 if (!isa_and_nonnull<ACC_DATA_CLAUSE_OPS>(op))
102 if (getDataClauseRemarkPrefix(op).empty())
104 if (op->getNumResults() == 0)
108 return !varName.empty();
116static bool reportIfNotPresent(
Operation *op) {
118 case acc::DataClause::acc_copyin:
119 case acc::DataClause::acc_copyin_readonly:
120 case acc::DataClause::acc_copyout:
121 case acc::DataClause::acc_copyout_zero:
122 case acc::DataClause::acc_copy:
123 case acc::DataClause::acc_create:
124 case acc::DataClause::acc_create_zero:
125 case acc::DataClause::acc_no_create:
127 case acc::DataClause::acc_present:
128 case acc::DataClause::acc_delete:
129 case acc::DataClause::acc_attach:
130 case acc::DataClause::acc_detach:
131 case acc::DataClause::acc_private:
132 case acc::DataClause::acc_firstprivate:
133 case acc::DataClause::acc_deviceptr:
134 case acc::DataClause::acc_getdeviceptr:
135 case acc::DataClause::acc_update_host:
136 case acc::DataClause::acc_update_self:
137 case acc::DataClause::acc_update_device:
138 case acc::DataClause::acc_use_device:
139 case acc::DataClause::acc_declare_device_resident:
140 case acc::DataClause::acc_declare_link:
141 case acc::DataClause::acc_cache:
142 case acc::DataClause::acc_cache_readonly:
144 case acc::DataClause::acc_reduction:
145 return isa<acc::CopyinOp>(op);
147 llvm_unreachable(
"Unhandled data clause");
150static void emitDataMappingRemarks(
ValueRange mappingOperands,
151 StringRef directivePrefix,
153 if (mappingOperands.empty())
163 mappingOps.reserve(mappingOperands.size());
164 for (
Value operand : mappingOperands) {
165 Operation *defOp = operand.getDefiningOp();
167 if (!shouldReport(defOp, accSupport, varName))
169 mappingOps.push_back({defOp, std::move(varName)});
171 if (mappingOps.empty())
174 llvm::sort(mappingOps, [](
const MappingInfo &
lhs,
const MappingInfo &
rhs) {
177 if (lhsClause == rhsClause) {
180 if (lhsImplicit == rhsImplicit)
181 return lhs.varName <
rhs.varName;
182 return lhsImplicit < rhsImplicit;
184 return lhsClause < rhsClause;
187 for (
auto *it = mappingOps.begin(); it != mappingOps.end(); ++it) {
191 while (std::next(it) != mappingOps.end() &&
192 reportOnSameLine(op, std::next(it)->op)) {
194 groupedOps.push_back(it);
201 std::string message =
"Generating ";
202 message += directivePrefix.str();
204 message +=
"default ";
206 message +=
"implicit ";
207 message += getDataClauseRemarkPrefix(op).str();
208 message += groupedOps.front()->varName;
209 for (MappingInfo *grouped : llvm::drop_begin(groupedOps)) {
211 message += grouped->varName;
214 if (reportIfNotPresent(op))
215 message +=
" [if not already present]";
222class ACCEmitRemarksData
225 using ACCEmitRemarksDataBase<ACCEmitRemarksData>::ACCEmitRemarksDataBase;
227 void runOnOperation()
override {
228 func::FuncOp
func = getOperation();
230 auto cachedAnalysis = getCachedParentAnalysis<acc::OpenACCSupport>();
232 ? cachedAnalysis->get()
233 : getAnalysis<acc::OpenACCSupport>();
242 .Case<acc::DataOp, acc::KernelEnvironmentOp>([&](
auto dataOp) {
243 emitDataMappingRemarks(dataOp.getDataClauseOperands(),
"",
246 .Case<acc::EnterDataOp>([&](acc::EnterDataOp enterOp) {
247 emitDataMappingRemarks(enterOp.getDataClauseOperands(),
248 "enter data ", accSupport);
250 .Case<acc::ExitDataOp>([&](acc::ExitDataOp exitOp) {
251 emitDataMappingRemarks(exitOp.getDataClauseOperands(),
"exit data ",
254 .Case<acc::UpdateOp>([&](acc::UpdateOp updateOp) {
255 emitDataMappingRemarks(updateOp.getDataClauseOperands(),
"",
258 .Case<acc::DeclareEnterOp>([&](acc::DeclareEnterOp declareEnterOp) {
259 if (isStructuredDeclareEnter(declareEnterOp))
260 emitDataMappingRemarks(declareEnterOp.getDataClauseOperands(),
"",
Operation is the basic unit of execution within MLIR.
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
remark::detail::InFlightRemark emitRemark(Operation *op, std::function< std::string()> messageFn, llvm::StringRef category="openacc")
Emit an OpenACC remark with lazy message generation.
std::string getVariableName(Value v)
Get the variable name for a given value.
static constexpr StringLiteral getFromDefaultClauseAttrName()
std::optional< mlir::acc::DataClause > getDataClause(mlir::Operation *accDataEntryOp)
Used to obtain the dataClause from a data entry operation.
bool getImplicitFlag(mlir::Operation *accDataEntryOp)
Used to find out whether data operation is implicit.
Include the generated interface declarations.
llvm::TypeSwitch< T, ResultT > TypeSwitch