50#define GEN_PASS_DEF_ACCROUTINELOWERING
51#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
55#define DEBUG_TYPE "acc-routine-lowering"
63static ParLevel computeParLevel(RoutineOp routineOp, DeviceType deviceType) {
64 auto gangDim = routineOp.getGangDimValue(deviceType);
66 gangDim = routineOp.getGangDimValue();
70 return ParLevel::gang_dim1;
72 return ParLevel::gang_dim2;
74 return ParLevel::gang_dim3;
79 if (routineOp.hasGang(deviceType) || routineOp.hasGang())
80 return ParLevel::gang_dim1;
81 if (routineOp.hasWorker(deviceType) || routineOp.hasWorker())
82 return ParLevel::worker;
83 if (routineOp.hasVector(deviceType) || routineOp.hasVector())
84 return ParLevel::vector;
91 for (
Block &block :
func.getBody().getBlocks()) {
92 if (
auto returnOp = dyn_cast<func::ReturnOp>(block.getTerminator())) {
93 result.assign(returnOp.operand_begin(), returnOp.operand_end());
101static func::FuncOp createFunctionForDeviceStaging(func::FuncOp hostFunc,
107 FunctionType funcType = hostFunc.getFunctionType();
108 func::FuncOp deviceFunc =
109 func::FuncOp::create(rewriter, loc, hostFunc.getName(), funcType);
110 deviceFunc->setAttrs(hostFunc->getAttrs());
113 SpecializedRoutineAttr::get(
114 ctx, SymbolRefAttr::get(ctx, routineOp.getSymName()),
115 ParLevelAttr::get(ctx, parLevel),
116 StringAttr::get(ctx, hostFunc.getName())));
118 Block *sourceBlock = &hostFunc.getBody().
front();
121 newBlock->
addArgument(arg.getType(), hostFunc.getLoc());
129buildRoutineBody(func::FuncOp deviceFunc, func::FuncOp hostFunc,
132 Block *newBlock = &deviceFunc.getBody().
front();
133 Block *sourceBlock = &hostFunc.getBody().
front();
138 GPUParallelDimAttr parDim = policy.
map(ctx, parLevel);
139 Value parWidthVal = ParWidthOp::create(rewriter, loc,
Value(), parDim);
154 loc, {parWidthVal}, inputArgs, RoutineOp::getOperationName(),
155 hostFunc.getBody(), rewriter, mapping,
157 {}, {}, sourceArgsToMap);
162 if (funcReturnVals.empty())
163 func::ReturnOp::create(rewriter, loc);
165 func::ReturnOp::create(rewriter, loc, computeRegion.getResults());
171static void finalizeRoutines(
174 for (
auto &[deviceFunc, routineOp] : accRoutineInfo) {
175 routineOp.setFuncNameAttr(SymbolRefAttr::get(ctx, deviceFunc.getName()));
176 routineOp->moveBefore(deviceFunc);
180class ACCRoutineLowering
183 using ACCRoutineLoweringBase::ACCRoutineLoweringBase;
185 void runOnOperation()
override {
186 ModuleOp mod = getOperation();
187 if (mod.getOps<RoutineOp>().empty()) {
188 LLVM_DEBUG(llvm::dbgs()
189 <<
"Skipping ACCRoutineLowering - no acc.routine ops\n");
201 for (RoutineOp routineOp : mod.getOps<RoutineOp>()) {
202 if (routineOp.getBindNameValue() ||
203 routineOp.getBindNameValue(deviceType))
206 func::FuncOp hostFunc = symTab.
lookup<func::FuncOp>(
207 routineOp.getFuncName().getLeafReference());
209 routineOp.emitError(
"acc routine function not found in symbol table");
210 return signalPassFailure();
212 if (hostFunc.isExternal())
216 getReturnValues(hostFunc, funcReturnVals);
219 ParLevel parLevel = computeParLevel(routineOp, deviceType);
220 func::FuncOp deviceFunc = createFunctionForDeviceStaging(
221 hostFunc, routineOp, parLevel, ctx, rewriter);
222 if (failed(buildRoutineBody(deviceFunc, hostFunc, funcReturnVals,
223 parLevel, policy, rewriter)))
224 return signalPassFailure();
226 accRoutineInfo.push_back({deviceFunc, routineOp});
227 symTab.
insert(deviceFunc);
230 finalizeRoutines(accRoutineInfo, ctx);
This class represents an argument of a Block.
Block represents an ordered list of Operations.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
BlockArgListType getArguments()
MLIRContext * getContext() const
This is a utility class for mapping one set of IR entities to another.
This class coordinates rewriting a piece of IR outside of a pattern rewrite, providing a way to keep ...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
RAII guard to reset the insertion point of the builder when destroyed.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
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.
StringAttr insert(Operation *symbol, Block::iterator insertPt={})
Insert a new symbol into the table, and rename it as necessary to avoid collisions.
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...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Default policy that provides the standard GPU mapping: gang(dim:1) -> BlockX (gridDim....
mlir::acc::GPUParallelDimAttr map(MLIRContext *ctx, ParLevel level) const override
Map an OpenACC parallelism level to target dimension.
static constexpr StringLiteral getSpecializedRoutineAttrName()
ComputeRegionOp buildComputeRegion(Location loc, ValueRange launchArgs, ValueRange inputArgs, llvm::StringRef origin, Region ®ionToClone, RewriterBase &rewriter, IRMapping &mapping, ValueRange output={}, FlatSymbolRefAttr kernelFuncName={}, FlatSymbolRefAttr kernelModuleName={}, Value stream={}, ValueRange inputArgsToMap={})
Build an acc.compute_region operation by cloning a source region.
static constexpr StringLiteral getRoutineInfoAttrName()
Include the generated interface declarations.