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 Block &block = atomicUpdateOp.getRegion().front();
147 rewriter.
clone(op, mapping);
150 if (!ptrLikeType.genStore(rewriter, atomicUpdateOp.getLoc(),
result,
152 accSupport.emitNYI(atomicUpdateOp.getLoc(),
153 "failed to generate store for atomic update");
156 rewriter.
eraseOp(atomicUpdateOp);
158 accSupport.emitNYI(atomicUpdateOp.getLoc(),
159 "unsupported type for atomic update");
166 OpenACCSupport &accSupport;
171class ACCOrphanAtomicReadOpConversion
174 ACCOrphanAtomicReadOpConversion(MLIRContext *ctx, OpenACCSupport &support)
175 : OpRewritePattern<acc::AtomicReadOp>(ctx), accSupport(support) {}
177 LogicalResult matchAndRewrite(acc::AtomicReadOp readOp,
178 PatternRewriter &rewriter)
const override {
183 Value x = readOp.getX();
184 Value v = readOp.getV();
185 auto xPtrType = dyn_cast<acc::PointerLikeType>(x.
getType());
186 auto vPtrType = dyn_cast<acc::PointerLikeType>(v.
getType());
187 if (xPtrType && vPtrType) {
188 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
189 auto vTyped = cast<TypedValue<acc::PointerLikeType>>(v);
193 if (!xPtrType.genCopy(rewriter, readOp.getLoc(), vTyped, xTyped, {})) {
194 accSupport.emitNYI(readOp.getLoc(),
195 "failed to generate copy for atomic read");
200 accSupport.emitNYI(readOp.getLoc(),
"unsupported type for atomic read");
207 OpenACCSupport &accSupport;
212class ACCOrphanAtomicWriteOpConversion
215 ACCOrphanAtomicWriteOpConversion(MLIRContext *ctx, OpenACCSupport &support)
216 : OpRewritePattern<acc::AtomicWriteOp>(ctx), accSupport(support) {}
218 LogicalResult matchAndRewrite(acc::AtomicWriteOp writeOp,
219 PatternRewriter &rewriter)
const override {
224 Value x = writeOp.getX();
225 Value expr = writeOp.getExpr();
226 auto ptrLikeType = dyn_cast<acc::PointerLikeType>(x.
getType());
228 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
230 if (!ptrLikeType.genStore(rewriter, writeOp.getLoc(), expr, xTyped)) {
231 accSupport.emitNYI(writeOp.getLoc(),
232 "failed to generate store for atomic write");
237 accSupport.emitNYI(writeOp.getLoc(),
"unsupported type for atomic write");
244 OpenACCSupport &accSupport;
251class ACCOrphanAtomicCaptureOpConversion
253 using OpRewritePattern<acc::AtomicCaptureOp>::OpRewritePattern;
255 LogicalResult matchAndRewrite(acc::AtomicCaptureOp captureOp,
256 PatternRewriter &rewriter)
const override {
261 assert(captureOp.getRegion().hasOneBlock() &&
"expected one block");
262 Block *block = &captureOp.getRegion().
front();
274 using OpRewritePattern<acc::LoopOp>::OpRewritePattern;
276 LogicalResult matchAndRewrite(acc::LoopOp loopOp,
277 PatternRewriter &rewriter)
const override {
282 if (loopOp.getUnstructured()) {
287 rewriter.
replaceOp(loopOp, executeRegion);
300static bool isUsedByComputeOrLoop(
Operation *op) {
302 if (isa<acc::ParallelOp, acc::SerialOp, acc::KernelsOp, acc::LoopOp>(user))
310template <
typename OpTy>
312 using OpRewritePattern<OpTy>::OpRewritePattern;
314 LogicalResult matchAndRewrite(OpTy op,
315 PatternRewriter &rewriter)
const override {
329class ACCSpecializeForHost
332 using ACCSpecializeForHostBase<
333 ACCSpecializeForHost>::ACCSpecializeForHostBase;
335 void runOnOperation()
override {
336 LLVM_DEBUG(llvm::dbgs() <<
"Enter ACCSpecializeForHost()\n");
338 func::FuncOp funcOp = getOperation();
343 RewritePatternSet patterns(context);
344 OpenACCSupport &accSupport = getAnalysis<OpenACCSupport>();
345 if (enableHostFallback)
349 GreedyRewriteConfig config;
358 LLVM_DEBUG(llvm::dbgs() <<
"Exit ACCSpecializeForHost()\n");
369 bool enableLoopConversion) {
387 if (enableLoopConversion)
388 patterns.
insert<ACCOrphanLoopOpConversion>(context);
391 patterns.
insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
392 patterns.
insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
393 patterns.
insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
394 patterns.
insert<ACCOrphanAtomicCaptureOpConversion>(context);
398 patterns.
insert<ACCOrphanDataEntryConversion<acc::CacheOp>,
399 ACCOrphanDataEntryConversion<acc::PrivateOp>,
400 ACCOrphanDataEntryConversion<acc::FirstprivateOp>,
401 ACCOrphanDataEntryConversion<acc::ReductionOp>>(context);
406 bool enableLoopConversion) {
416 if (enableLoopConversion)
417 patterns.
insert<ACCOrphanLoopOpConversion>(context);
422 patterns.
insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
423 patterns.
insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
424 patterns.
insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
425 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.
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
static constexpr int64_t kNoLimit
GreedyRewriteConfig & setMaxIterations(int64_t iterations)
GreedyRewriteConfig & setUseTopDownTraversal(bool use=true)
auto lookup(T from) const
Lookup a mapped value within the map.
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.
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.
RewritePatternSet & insert(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
MLIRContext * getContext() const
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.
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...
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...