61#define DEBUG_TYPE "acc-implicit-routine"
65#define GEN_PASS_DEF_ACCIMPLICITROUTINE
66#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
74class ACCImplicitRoutine
77 unsigned routineCounter = 0;
78 static constexpr llvm::StringRef accRoutinePrefix =
"acc_routine_";
81 void initRoutineCounter(ModuleOp module) {
82 module.walk([&](acc::RoutineOp routineOp) { routineCounter++; });
88 bool isACCRoutineBindDefaultOrDeviceType(acc::RoutineOp op,
89 acc::DeviceType deviceType) {
91 if (!op.getBindIdName() && !op.getBindStrName())
93 return op.getBindNameValue().has_value() ||
94 op.getBindNameValue(deviceType).has_value();
99 FunctionOpInterface &callee) {
100 std::string routineName =
101 (accRoutinePrefix + std::to_string(routineCounter++)).str();
102 auto routineOp = acc::RoutineOp::create(
107 mlir::SymbolRefAttr::get(builder.
getContext(),
124 "function is already associated with a routine");
126 callee->setDiscardableAttr(
128 mlir::acc::RoutineInfoAttr::get(
130 {mlir::SymbolRefAttr::get(builder.getContext(),
131 builder.getStringAttr(routineName))}));
141 op->
walk([&](CallOpInterface callOp) {
142 if (!callOp.getCallableForCallee())
145 auto calleeSymbolRef =
146 dyn_cast<SymbolRefAttr>(callOp.getCallableForCallee());
149 if (!calleeSymbolRef)
152 auto callee = symTab.
lookup<FunctionOpInterface>(
153 calleeSymbolRef.getLeafReference().str());
165 if (callee.isExternal()) {
166 callOp->emitError() <<
"Calls in an acc compute region must be marked "
168 << calleeSymbolRef.getLeafReference();
173 createRoutineOp(builder, callee.getLoc(), callee);
179 LogicalResult implicitRoutineForCallsInRoutine(
186 if (isACCRoutineBindDefaultOrDeviceType(routineOp, targetDeviceType))
189 SymbolTable symTab(routineOp->getParentOfType<ModuleOp>());
190 std::queue<acc::RoutineOp> routineQueue;
191 routineQueue.push(routineOp);
193 while (!routineQueue.empty()) {
194 auto currentRoutine = routineQueue.front();
196 auto func = symTab.
lookup<FunctionOpInterface>(
197 currentRoutine.getFuncName().getLeafReference());
198 func.walk([&](CallOpInterface callOp) {
199 if (!callOp.getCallableForCallee())
202 auto calleeSymbolRef =
203 dyn_cast<SymbolRefAttr>(callOp.getCallableForCallee());
206 if (!calleeSymbolRef)
209 auto callee = symTab.
lookup<FunctionOpInterface>(
210 calleeSymbolRef.getLeafReference().str());
222 if (callee.isExternal()) {
224 <<
"Calls in acc routine must also be marked with acc routine: "
225 << calleeSymbolRef.getLeafReference();
230 auto newRoutineOp = createRoutineOp(builder, callee.getLoc(), callee);
231 routineQueue.push(newRoutineOp);
238 using ACCImplicitRoutineBase<ACCImplicitRoutine>::ACCImplicitRoutineBase;
240 void runOnOperation()
override {
241 auto module = getOperation();
244 initRoutineCounter(module);
251 module.walk([&](Operation *op) {
252 if (isa<ACC_COMPUTE_CONSTRUCT_OPS>(op))
253 if (failed(implicitRoutineForCallsInComputeRegions(op, symTab, builder,
259 acc::DeviceType targetDeviceType = deviceType;
262 module.walk([&](acc::RoutineOp routineOp) {
263 if (failed(implicitRoutineForCallsInRoutine(
264 routineOp, builder, accSupport, targetDeviceType)))
269 return signalPassFailure();
StringAttr getStringAttr(const Twine &bytes)
MLIRContext * getContext() const
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
Operation is the basic unit of execution within MLIR.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
This class allows for representing and managing the symbol table used by operations with the 'SymbolT...
Operation * lookup(StringRef name) const
Look up a symbol with the specified name, returning null if no such name exists.
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr=nullptr)
Check if a symbol use is valid for use in an OpenACC region.
static constexpr StringLiteral getRoutineInfoAttrName()
Include the generated interface declarations.