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->setDiscardableAttrs(
111 hostFunc->getDiscardableAttrDictionary().getValue());
113 deviceFunc->setDiscardableAttr(
115 SpecializedRoutineAttr::get(
116 ctx, SymbolRefAttr::get(ctx, routineOp.getSymName()),
117 ParLevelAttr::get(ctx, parLevel),
118 StringAttr::get(ctx, hostFunc.getName())));
120 Block *sourceBlock = &hostFunc.getBody().
front();
123 newBlock->
addArgument(arg.getType(), hostFunc.getLoc());
131buildRoutineBody(func::FuncOp deviceFunc, func::FuncOp hostFunc,
134 Block *newBlock = &deviceFunc.getBody().
front();
135 Block *sourceBlock = &hostFunc.getBody().
front();
140 GPUParallelDimAttr parDim = policy.
map(ctx, parLevel);
141 Value parWidthVal = ParWidthOp::create(rewriter, loc,
Value(), parDim);
156 loc, {parWidthVal}, inputArgs, RoutineOp::getOperationName(),
157 hostFunc.getBody(), rewriter, mapping,
159 {}, {}, sourceArgsToMap);
164 if (funcReturnVals.empty())
165 func::ReturnOp::create(rewriter, loc);
167 func::ReturnOp::create(rewriter, loc, computeRegion.getResults());
173static void finalizeRoutines(
176 for (
auto &[deviceFunc, routineOp] : accRoutineInfo) {
177 routineOp.setFuncNameAttr(SymbolRefAttr::get(ctx, deviceFunc.getName()));
178 routineOp->moveBefore(deviceFunc);
182class ACCRoutineLowering
183 :
public acc::impl::ACCRoutineLoweringBase<ACCRoutineLowering> {
185 using ACCRoutineLoweringBase::ACCRoutineLoweringBase;
187 void runOnOperation()
override {
188 ModuleOp mod = getOperation();
189 if (mod.getOps<RoutineOp>().empty()) {
190 LLVM_DEBUG(llvm::dbgs()
191 <<
"Skipping ACCRoutineLowering - no acc.routine ops\n");
203 for (RoutineOp routineOp : mod.getOps<RoutineOp>()) {
204 if (routineOp.getBindNameValue() ||
205 routineOp.getBindNameValue(deviceType))
208 func::FuncOp hostFunc = symTab.
lookup<func::FuncOp>(
209 routineOp.getFuncName().getLeafReference());
211 routineOp.emitError(
"acc routine function not found in symbol table");
212 return signalPassFailure();
214 if (hostFunc.isExternal())
218 getReturnValues(hostFunc, funcReturnVals);
221 ParLevel parLevel = computeParLevel(routineOp, deviceType);
222 func::FuncOp deviceFunc = createFunctionForDeviceStaging(
223 hostFunc, routineOp, parLevel, ctx, rewriter);
224 if (failed(buildRoutineBody(deviceFunc, hostFunc, funcReturnVals,
225 parLevel, policy, rewriter)))
226 return signalPassFailure();
228 accRoutineInfo.push_back({deviceFunc, routineOp});
229 symTab.
insert(deviceFunc);
232 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.