95#define GEN_PASS_DEF_ACCSPECIALIZEFORHOST
96#include "mlir/Dialect/OpenACC/Transforms/Passes.h.inc"
100#define DEBUG_TYPE "acc-specialize-for-host"
108 if (isa<ACC_COMPUTE_CONSTRUCT_OPS>(op))
118class ACCOrphanAtomicUpdateOpConversion
121 ACCOrphanAtomicUpdateOpConversion(MLIRContext *ctx, OpenACCSupport &support)
122 : OpRewritePattern<acc::AtomicUpdateOp>(ctx), accSupport(support) {}
124 LogicalResult matchAndRewrite(acc::AtomicUpdateOp atomicUpdateOp,
125 PatternRewriter &rewriter)
const override {
130 Value x = atomicUpdateOp.getX();
132 auto ptrLikeType = dyn_cast<acc::PointerLikeType>(type);
134 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
137 ptrLikeType.genLoad(rewriter, atomicUpdateOp.getLoc(), xTyped, {});
139 accSupport.emitNYI(atomicUpdateOp.getLoc(),
140 "failed to generate load for atomic update");
144 mapping.
map(atomicUpdateOp.getRegion().front().getArgument(0), loadOp);
145 Operation *expr = rewriter.
clone(*atomicUpdateOp.getFirstOp(), mapping);
146 if (!ptrLikeType.genStore(rewriter, atomicUpdateOp.getLoc(),
148 accSupport.emitNYI(atomicUpdateOp.getLoc(),
149 "failed to generate store for atomic update");
152 rewriter.
eraseOp(atomicUpdateOp);
154 accSupport.emitNYI(atomicUpdateOp.getLoc(),
155 "unsupported type for atomic update");
162 OpenACCSupport &accSupport;
167class ACCOrphanAtomicReadOpConversion
170 ACCOrphanAtomicReadOpConversion(MLIRContext *ctx, OpenACCSupport &support)
171 : OpRewritePattern<acc::AtomicReadOp>(ctx), accSupport(support) {}
173 LogicalResult matchAndRewrite(acc::AtomicReadOp readOp,
174 PatternRewriter &rewriter)
const override {
179 Value x = readOp.getX();
180 Value v = readOp.getV();
181 auto xPtrType = dyn_cast<acc::PointerLikeType>(x.
getType());
182 auto vPtrType = dyn_cast<acc::PointerLikeType>(v.
getType());
183 if (xPtrType && vPtrType) {
184 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
185 auto vTyped = cast<TypedValue<acc::PointerLikeType>>(v);
189 if (!xPtrType.genCopy(rewriter, readOp.getLoc(), vTyped, xTyped, {})) {
190 accSupport.emitNYI(readOp.getLoc(),
191 "failed to generate copy for atomic read");
196 accSupport.emitNYI(readOp.getLoc(),
"unsupported type for atomic read");
203 OpenACCSupport &accSupport;
208class ACCOrphanAtomicWriteOpConversion
211 ACCOrphanAtomicWriteOpConversion(MLIRContext *ctx, OpenACCSupport &support)
212 : OpRewritePattern<acc::AtomicWriteOp>(ctx), accSupport(support) {}
214 LogicalResult matchAndRewrite(acc::AtomicWriteOp writeOp,
215 PatternRewriter &rewriter)
const override {
220 Value x = writeOp.getX();
221 Value expr = writeOp.getExpr();
222 auto ptrLikeType = dyn_cast<acc::PointerLikeType>(x.
getType());
224 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
226 if (!ptrLikeType.genStore(rewriter, writeOp.getLoc(), expr, xTyped)) {
227 accSupport.emitNYI(writeOp.getLoc(),
228 "failed to generate store for atomic write");
233 accSupport.emitNYI(writeOp.getLoc(),
"unsupported type for atomic write");
240 OpenACCSupport &accSupport;
247class ACCOrphanAtomicCaptureOpConversion
249 using OpRewritePattern<acc::AtomicCaptureOp>::OpRewritePattern;
251 LogicalResult matchAndRewrite(acc::AtomicCaptureOp captureOp,
252 PatternRewriter &rewriter)
const override {
257 assert(captureOp.getRegion().hasOneBlock() &&
"expected one block");
258 Block *block = &captureOp.getRegion().front();
270 using OpRewritePattern<acc::LoopOp>::OpRewritePattern;
272 LogicalResult matchAndRewrite(acc::LoopOp loopOp,
273 PatternRewriter &rewriter)
const override {
278 if (loopOp.getUnstructured()) {
283 rewriter.
replaceOp(loopOp, executeRegion);
296static bool isUsedByComputeOrLoop(
Operation *op) {
298 if (isa<acc::ParallelOp, acc::SerialOp, acc::KernelsOp, acc::LoopOp>(user))
306template <
typename OpTy>
308 using OpRewritePattern<OpTy>::OpRewritePattern;
310 LogicalResult matchAndRewrite(OpTy op,
311 PatternRewriter &rewriter)
const override {
325class ACCSpecializeForHost
326 :
public acc::impl::ACCSpecializeForHostBase<ACCSpecializeForHost> {
328 using ACCSpecializeForHostBase<
329 ACCSpecializeForHost>::ACCSpecializeForHostBase;
331 void runOnOperation()
override {
332 LLVM_DEBUG(llvm::dbgs() <<
"Enter ACCSpecializeForHost()\n");
334 func::FuncOp funcOp = getOperation();
339 RewritePatternSet
patterns(context);
340 OpenACCSupport &accSupport = getAnalysis<OpenACCSupport>();
341 if (enableHostFallback)
345 GreedyRewriteConfig
config;
346 config.setUseTopDownTraversal(
true);
351 LLVM_DEBUG(llvm::dbgs() <<
"Exit ACCSpecializeForHost()\n");
362 bool enableLoopConversion) {
380 if (enableLoopConversion)
381 patterns.insert<ACCOrphanLoopOpConversion>(context);
384 patterns.insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
385 patterns.insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
386 patterns.insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
387 patterns.insert<ACCOrphanAtomicCaptureOpConversion>(context);
391 patterns.insert<ACCOrphanDataEntryConversion<acc::CacheOp>,
392 ACCOrphanDataEntryConversion<acc::PrivateOp>,
393 ACCOrphanDataEntryConversion<acc::FirstprivateOp>,
394 ACCOrphanDataEntryConversion<acc::ReductionOp>>(context);
399 bool enableLoopConversion) {
409 if (enableLoopConversion)
410 patterns.insert<ACCOrphanLoopOpConversion>(context);
415 patterns.insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
416 patterns.insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
417 patterns.insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
418 patterns.insert<ACCOrphanAtomicCaptureOpConversion>(context);
static bool isInsideACCComputeConstruct(Operation *op)
Check if an operation is inside an ACC compute construct.
Operation * getTerminator()
Get the terminator operation of this block.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
user_range getUsers()
Returns a range of all users.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
virtual void inlineBlockBefore(Block *source, Block *dest, Block::iterator before, ValueRange argValues={})
Inline the operations of block 'source' into block 'dest' before the given position.
Type getType() const
Return the type of this value.
Pattern to erase acc.declare_enter and its associated acc.declare_exit.
Pattern to simply erase an ACC op (for ops with no results).
Pattern to replace an ACC op with its var operand.
Pattern to unwrap a region from an ACC op and erase the wrapper.
bool isSpecializedAccRoutine(mlir::Operation *op)
Used to check whether this is a specialized accelerator version of acc routine function.
scf::ExecuteRegionOp convertUnstructuredACCLoopToSCFExecuteRegion(LoopOp loopOp, RewriterBase &rewriter)
Convert an unstructured acc.loop to scf.execute_region.
void populateACCOrphanToHostPatterns(RewritePatternSet &patterns, OpenACCSupport &accSupport, bool enableLoopConversion=true)
Populates patterns for converting orphan ACC operations to host.
void populateACCHostFallbackPatterns(RewritePatternSet &patterns, OpenACCSupport &accSupport, bool enableLoopConversion=true)
Populates all patterns for host fallback path (when if clause evaluates to false).
scf::ForOp convertACCLoopToSCFFor(LoopOp loopOp, RewriterBase &rewriter, bool enableCollapse)
Convert a structured acc.loop to scf.for.
Include the generated interface declarations.
const FrozenRewritePatternSet GreedyRewriteConfig config
LogicalResult applyPatternsGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
const FrozenRewritePatternSet & patterns
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...