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))
107 if (getDataClauseRemarkPrefix(op).empty())
109 if (op->getNumResults() == 0)
113 return !varName.empty();
121static bool reportIfNotPresent(
Operation *op) {
123 case acc::DataClause::acc_copyin:
124 case acc::DataClause::acc_copyin_readonly:
125 case acc::DataClause::acc_copyout:
126 case acc::DataClause::acc_copyout_zero:
127 case acc::DataClause::acc_copy:
128 case acc::DataClause::acc_create:
129 case acc::DataClause::acc_create_zero:
130 case acc::DataClause::acc_no_create:
132 case acc::DataClause::acc_present:
133 case acc::DataClause::acc_delete:
134 case acc::DataClause::acc_attach:
135 case acc::DataClause::acc_detach:
136 case acc::DataClause::acc_private:
137 case acc::DataClause::acc_firstprivate:
138 case acc::DataClause::acc_deviceptr:
139 case acc::DataClause::acc_getdeviceptr:
140 case acc::DataClause::acc_update_host:
141 case acc::DataClause::acc_update_self:
142 case acc::DataClause::acc_update_device:
143 case acc::DataClause::acc_use_device:
144 case acc::DataClause::acc_declare_device_resident:
145 case acc::DataClause::acc_declare_link:
146 case acc::DataClause::acc_cache:
147 case acc::DataClause::acc_cache_readonly:
149 case acc::DataClause::acc_reduction:
150 return isa<acc::CopyinOp>(op);
152 llvm_unreachable(
"Unhandled data clause");
155static void emitDataMappingRemarks(
ValueRange mappingOperands,
156 StringRef directivePrefix,
158 if (mappingOperands.empty())
168 mappingOps.reserve(mappingOperands.size());
169 for (
Value operand : mappingOperands) {
170 Operation *defOp = operand.getDefiningOp();
172 if (!shouldReport(defOp, accSupport, varName))
174 mappingOps.push_back({defOp, std::move(varName)});
176 if (mappingOps.empty())
179 llvm::sort(mappingOps, [](
const MappingInfo &lhs,
const MappingInfo &rhs) {
182 if (lhsClause == rhsClause) {
185 if (lhsImplicit == rhsImplicit)
186 return lhs.varName < rhs.varName;
187 return lhsImplicit < rhsImplicit;
189 return lhsClause < rhsClause;
192 for (
auto *it = mappingOps.begin(); it != mappingOps.end(); ++it) {
196 while (std::next(it) != mappingOps.end() &&
197 reportOnSameLine(op, std::next(it)->op)) {
199 groupedOps.push_back(it);
206 std::string message =
"Generating ";
207 message += directivePrefix.str();
209 message +=
"default ";
211 message +=
"implicit ";
212 message += getDataClauseRemarkPrefix(op).str();
213 message += groupedOps.front()->varName;
214 for (MappingInfo *grouped : llvm::drop_begin(groupedOps)) {
216 message += grouped->varName;
219 if (reportIfNotPresent(op))
220 message +=
" [if not already present]";
227class ACCEmitRemarksData
228 :
public acc::impl::ACCEmitRemarksDataBase<ACCEmitRemarksData> {
230 using ACCEmitRemarksDataBase<ACCEmitRemarksData>::ACCEmitRemarksDataBase;
232 void runOnOperation()
override {
233 func::FuncOp
func = getOperation();
235 auto cachedAnalysis = getCachedParentAnalysis<acc::OpenACCSupport>();
237 ? cachedAnalysis->get()
238 : getAnalysis<acc::OpenACCSupport>();
247 .Case<acc::DataOp, acc::KernelEnvironmentOp>([&](
auto dataOp) {
248 emitDataMappingRemarks(dataOp.getDataClauseOperands(),
"",
251 .Case<acc::EnterDataOp>([&](acc::EnterDataOp enterOp) {
252 emitDataMappingRemarks(enterOp.getDataClauseOperands(),
253 "enter data ", accSupport);
255 .Case<acc::ExitDataOp>([&](acc::ExitDataOp exitOp) {
256 emitDataMappingRemarks(exitOp.getDataClauseOperands(),
"exit data ",
259 .Case<acc::UpdateOp>([&](acc::UpdateOp updateOp) {
260 emitDataMappingRemarks(updateOp.getDataClauseOperands(),
"",
263 .Case<acc::DeclareEnterOp>([&](acc::DeclareEnterOp declareEnterOp) {
264 if (isStructuredDeclareEnter(declareEnterOp))
265 emitDataMappingRemarks(declareEnterOp.getDataClauseOperands(),
"",
Operation is the basic unit of execution within MLIR.
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns a null Attribute if the discardable attribute does no...
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, VariableNameConfig config={})
Get the variable name for a given value.
bool getSyntheticFlag(mlir::Operation *accDataClauseOp)
Used to find out whether the implementation created the data operation for its own bookkeeping,...
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