67#define DEBUG_TYPE "acc-implicit-routine"
71#define GEN_PASS_DEF_ACCIMPLICITROUTINE
72#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
79class ACCImplicitRoutine
82 unsigned routineCounter = 0;
83 static constexpr llvm::StringRef accRoutinePrefix =
"acc_routine_";
86 void initRoutineCounter(ModuleOp module) {
87 module.walk([&](acc::RoutineOp routineOp) { routineCounter++; });
92 FunctionOpInterface &callee) {
93 std::string routineName =
94 (accRoutinePrefix + std::to_string(routineCounter++)).str();
95 auto routineOp = acc::RoutineOp::create(
100 mlir::SymbolRefAttr::get(builder.
getContext(),
117 "function is already associated with a routine");
119 callee->setDiscardableAttr(
121 mlir::acc::RoutineInfoAttr::get(
123 {mlir::SymbolRefAttr::get(builder.getContext(),
124 builder.getStringAttr(routineName))}));
134 op->
walk([&](CallOpInterface callOp) {
137 if (!callOp.getCallableForCallee())
140 auto calleeSymbolRef =
141 dyn_cast<SymbolRefAttr>(callOp.getCallableForCallee());
144 if (!calleeSymbolRef)
147 auto callee = symTab.
lookup<FunctionOpInterface>(
148 calleeSymbolRef.getLeafReference().str());
160 if (callee.isExternal()) {
161 callOp->emitError() <<
"Calls in an acc compute region must be marked "
163 << calleeSymbolRef.getLeafReference();
168 createRoutineOp(builder, callee.getLoc(), callee);
174 LogicalResult implicitRoutineForCallsInRoutine(
181 if (routineOp.getEffectiveBindName(targetDeviceType))
184 SymbolTable symTab(routineOp->getParentOfType<ModuleOp>());
185 std::queue<acc::RoutineOp> routineQueue;
186 routineQueue.push(routineOp);
188 while (!routineQueue.empty()) {
189 auto currentRoutine = routineQueue.front();
191 auto func = symTab.
lookup<FunctionOpInterface>(
192 currentRoutine.getFuncName().getLeafReference());
193 func.walk([&](CallOpInterface callOp) {
196 if (!callOp.getCallableForCallee())
199 auto calleeSymbolRef =
200 dyn_cast<SymbolRefAttr>(callOp.getCallableForCallee());
203 if (!calleeSymbolRef)
206 auto callee = symTab.
lookup<FunctionOpInterface>(
207 calleeSymbolRef.getLeafReference().str());
219 if (callee.isExternal()) {
221 <<
"Calls in acc routine must also be marked with acc routine: "
222 << calleeSymbolRef.getLeafReference();
227 auto newRoutineOp = createRoutineOp(builder, callee.getLoc(), callee);
228 routineQueue.push(newRoutineOp);
235 using ACCImplicitRoutineBase<ACCImplicitRoutine>::ACCImplicitRoutineBase;
238 ACCImplicitRoutineBase<ACCImplicitRoutine>::getDependentDialects(registry);
242 void runOnOperation()
override {
243 auto module = getOperation();
246 initRoutineCounter(module);
253 module.walk([&](Operation *op) {
254 if (isa<ACC_COMPUTE_CONSTRUCT_OPS>(op))
255 if (failed(implicitRoutineForCallsInComputeRegions(op, symTab, builder,
261 acc::DeviceType targetDeviceType = deviceType;
264 module.walk([&](acc::RoutineOp routineOp) {
265 if (failed(implicitRoutineForCallsInRoutine(
266 routineOp, builder, accSupport, targetDeviceType)))
271 return signalPassFailure();
StringAttr getStringAttr(const Twine &bytes)
MLIRContext * getContext() const
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
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()
void registerAllExtensions(DialectRegistry ®istry)
Register the standard OpenACC models for GPU, LLVM and MemRef IR.
bool isInOffTargetBranch(mlir::Operation *op, llvm::ArrayRef< int64_t > deviceTypes)
Returns true if op is in a branch that does not execute on the target.
Include the generated interface declarations.