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))
125class ACCOrphanAtomicUpdateOpConversion
128 ACCOrphanAtomicUpdateOpConversion(MLIRContext *ctx, OpenACCSupport &support)
129 : OpRewritePattern<acc::AtomicUpdateOp>(ctx), accSupport(support) {}
131 LogicalResult matchAndRewrite(acc::AtomicUpdateOp atomicUpdateOp,
132 PatternRewriter &rewriter)
const override {
136 Value x = atomicUpdateOp.getX();
138 auto ptrLikeType = dyn_cast<acc::PointerLikeType>(type);
140 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
143 ptrLikeType.genLoad(rewriter, atomicUpdateOp.getLoc(), xTyped, {});
145 accSupport.emitNYI(atomicUpdateOp.getLoc(),
146 "failed to generate load for atomic update");
150 mapping.
map(atomicUpdateOp.getRegion().front().getArgument(0), loadOp);
151 Block &block = atomicUpdateOp.getRegion().front();
153 rewriter.
clone(op, mapping);
156 if (!ptrLikeType.genStore(rewriter, atomicUpdateOp.getLoc(),
result,
158 accSupport.emitNYI(atomicUpdateOp.getLoc(),
159 "failed to generate store for atomic update");
162 rewriter.
eraseOp(atomicUpdateOp);
164 accSupport.emitNYI(atomicUpdateOp.getLoc(),
165 "unsupported type for atomic update");
172 OpenACCSupport &accSupport;
177class ACCOrphanAtomicReadOpConversion
180 ACCOrphanAtomicReadOpConversion(MLIRContext *ctx, OpenACCSupport &support)
181 : OpRewritePattern<acc::AtomicReadOp>(ctx), accSupport(support) {}
183 LogicalResult matchAndRewrite(acc::AtomicReadOp readOp,
184 PatternRewriter &rewriter)
const override {
188 Value x = readOp.getX();
189 Value v = readOp.getV();
190 auto xPtrType = dyn_cast<acc::PointerLikeType>(x.
getType());
191 auto vPtrType = dyn_cast<acc::PointerLikeType>(v.
getType());
192 if (xPtrType && vPtrType) {
193 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
194 auto vTyped = cast<TypedValue<acc::PointerLikeType>>(v);
198 if (!xPtrType.genCopy(rewriter, readOp.getLoc(), vTyped, xTyped, {})) {
199 accSupport.emitNYI(readOp.getLoc(),
200 "failed to generate copy for atomic read");
205 accSupport.emitNYI(readOp.getLoc(),
"unsupported type for atomic read");
212 OpenACCSupport &accSupport;
217class ACCOrphanAtomicWriteOpConversion
220 ACCOrphanAtomicWriteOpConversion(MLIRContext *ctx, OpenACCSupport &support)
221 : OpRewritePattern<acc::AtomicWriteOp>(ctx), accSupport(support) {}
223 LogicalResult matchAndRewrite(acc::AtomicWriteOp writeOp,
224 PatternRewriter &rewriter)
const override {
228 Value x = writeOp.getX();
229 Value expr = writeOp.getExpr();
230 auto ptrLikeType = dyn_cast<acc::PointerLikeType>(x.
getType());
232 auto xTyped = cast<TypedValue<acc::PointerLikeType>>(x);
234 if (!ptrLikeType.genStore(rewriter, writeOp.getLoc(), expr, xTyped)) {
235 accSupport.emitNYI(writeOp.getLoc(),
236 "failed to generate store for atomic write");
241 accSupport.emitNYI(writeOp.getLoc(),
"unsupported type for atomic write");
248 OpenACCSupport &accSupport;
255class ACCOrphanAtomicCaptureOpConversion
257 using OpRewritePattern<acc::AtomicCaptureOp>::OpRewritePattern;
259 LogicalResult matchAndRewrite(acc::AtomicCaptureOp captureOp,
260 PatternRewriter &rewriter)
const override {
265 assert(captureOp.getRegion().hasOneBlock() &&
"expected one block");
266 Block *block = &captureOp.getRegion().
front();
278 using OpRewritePattern<acc::LoopOp>::OpRewritePattern;
280 LogicalResult matchAndRewrite(acc::LoopOp loopOp,
281 PatternRewriter &rewriter)
const override {
286 if (loopOp.getUnstructured()) {
291 rewriter.
replaceOp(loopOp, executeRegion);
304static bool isUsedByComputeOrLoop(
Operation *op) {
306 if (isa<acc::ParallelOp, acc::SerialOp, acc::KernelsOp, acc::LoopOp>(user))
314template <
typename OpTy>
316 using OpRewritePattern<OpTy>::OpRewritePattern;
318 LogicalResult matchAndRewrite(OpTy op,
319 PatternRewriter &rewriter)
const override {
333class ACCSpecializeForHost
336 using ACCSpecializeForHostBase<
337 ACCSpecializeForHost>::ACCSpecializeForHostBase;
339 void runOnOperation()
override {
340 LLVM_DEBUG(llvm::dbgs() <<
"Enter ACCSpecializeForHost()\n");
342 func::FuncOp funcOp = getOperation();
347 RewritePatternSet patterns(context);
348 OpenACCSupport &accSupport = getAnalysis<OpenACCSupport>();
349 if (enableHostFallback)
353 GreedyRewriteConfig config;
362 LLVM_DEBUG(llvm::dbgs() <<
"Exit ACCSpecializeForHost()\n");
373 bool enableLoopConversion) {
391 if (enableLoopConversion)
392 patterns.
insert<ACCOrphanLoopOpConversion>(context);
395 patterns.
insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
396 patterns.
insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
397 patterns.
insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
398 patterns.
insert<ACCOrphanAtomicCaptureOpConversion>(context);
402 patterns.
insert<ACCOrphanDataEntryConversion<acc::CacheOp>,
403 ACCOrphanDataEntryConversion<acc::PrivateOp>,
404 ACCOrphanDataEntryConversion<acc::FirstprivateOp>,
405 ACCOrphanDataEntryConversion<acc::ReductionOp>>(context);
410 bool enableLoopConversion) {
420 if (enableLoopConversion)
421 patterns.
insert<ACCOrphanLoopOpConversion>(context);
426 patterns.
insert<ACCOrphanAtomicUpdateOpConversion>(context, accSupport);
427 patterns.
insert<ACCOrphanAtomicReadOpConversion>(context, accSupport);
428 patterns.
insert<ACCOrphanAtomicWriteOpConversion>(context, accSupport);
429 patterns.
insert<ACCOrphanAtomicCaptureOpConversion>(context);
static bool isAtomicConversionDeferred(Operation *op)
Return true if an enclosing compute construct or capture must be removed before converting an atomic ...
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...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
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...