MLIR 24.0.0git
OpenACCUtilsCG.cpp
Go to the documentation of this file.
1//===- OpenACCUtilsCG.cpp - OpenACC Code Generation Utilities -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements utility functions for OpenACC code generation.
10//
11//===----------------------------------------------------------------------===//
12
14
22#include "mlir/IR/BuiltinOps.h"
23#include "mlir/IR/IRMapping.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SmallVector.h"
28#include "llvm/ADT/TypeSwitch.h"
29#include "llvm/Support/MathExtras.h"
30
31namespace mlir {
32namespace acc {
33
34std::optional<DataLayout> getDataLayout(Operation *op, bool allowDefault) {
35 if (!op)
36 return std::nullopt;
37
38 // Walk up the parent chain to find the nearest operation with an explicit
39 // data layout spec. Check ModuleOp explicitly since it does not actually
40 // implement DataLayoutOpInterface as a trait (it just has the same methods).
41 Operation *current = op;
42 while (current) {
43 // Check for ModuleOp with explicit data layout spec
44 if (auto mod = llvm::dyn_cast<ModuleOp>(current)) {
45 if (mod.getDataLayoutSpec())
46 return DataLayout(mod);
47 } else if (auto dataLayoutOp =
48 llvm::dyn_cast<DataLayoutOpInterface>(current)) {
49 // Check other DataLayoutOpInterface implementations
50 if (dataLayoutOp.getDataLayoutSpec())
51 return DataLayout(dataLayoutOp);
52 }
53 current = current->getParentOp();
54 }
55
56 // No explicit data layout found; return default if allowed
57 if (allowDefault) {
58 // Check if op itself is a ModuleOp
59 if (auto mod = llvm::dyn_cast<ModuleOp>(op))
60 return DataLayout(mod);
61 // Otherwise check parents
62 if (auto mod = op->getParentOfType<ModuleOp>())
63 return DataLayout(mod);
64 }
65
66 return std::nullopt;
67}
68
69ComputeRegionOp buildComputeRegion(Location loc, ValueRange launchArgs,
70 ValueRange inputArgs, llvm::StringRef origin,
71 Region &regionToClone,
72 RewriterBase &rewriter, IRMapping &mapping,
73 ValueRange output,
74 FlatSymbolRefAttr kernelFuncName,
75 FlatSymbolRefAttr kernelModuleName,
76 Value stream, ValueRange inputArgsToMap) {
77 SmallVector<Type> resultTypes;
78 for (auto val : output)
79 resultTypes.push_back(val.getType());
80 auto computeRegion =
81 ComputeRegionOp::create(rewriter, loc, resultTypes, launchArgs, inputArgs,
82 stream, origin, kernelFuncName, kernelModuleName);
83
84 assert(!regionToClone.getBlocks().empty() &&
85 "empty region for acc.compute_region");
86 OpBuilder::InsertionGuard guard(rewriter);
87
88 ValueRange mapKeys = inputArgsToMap.empty() ? inputArgs : inputArgsToMap;
89 assert(mapKeys.size() == inputArgs.size() &&
90 "inputArgsToMap must have same size as inputArgs when provided");
91
92 Type indexType = rewriter.getIndexType();
93 Block *entryBlock = rewriter.createBlock(&computeRegion.getRegion());
94 for (size_t i = 0; i < launchArgs.size(); ++i)
95 entryBlock->addArgument(indexType, loc);
96 for (Value input : inputArgs)
97 entryBlock->addArgument(input.getType(), loc);
98 for (size_t i = 0; i < inputArgs.size(); ++i)
99 mapping.map(mapKeys[i], entryBlock->getArgument(launchArgs.size() + i));
100 rewriter.setInsertionPointToStart(entryBlock);
101 if (regionToClone.getBlocks().size() == 1) {
102 for (auto &op : regionToClone.front().getOperations()) {
103 if (op.hasTrait<OpTrait::IsTerminator>())
104 break;
105 rewriter.clone(op, mapping);
106 }
107 SmallVector<Value> yieldOperands;
108 for (auto val : output)
109 yieldOperands.push_back(mapping.lookup(val));
110 rewriter.setInsertionPointToEnd(entryBlock);
111 YieldOp::create(rewriter, loc, yieldOperands);
112 } else {
114 regionToClone, mapping, loc, rewriter);
115 if (!exeRegion) {
116 rewriter.eraseOp(computeRegion);
117 return nullptr;
118 }
120 llvm::to_vector(exeRegion.getOps<scf::YieldOp>()));
121 assert(!yieldOps.empty() &&
122 "multi-block region must contain at least one scf.yield");
123 assert(llvm::all_of(yieldOps,
124 [&output](scf::YieldOp yieldOp) {
125 return yieldOp.getNumOperands() ==
126 static_cast<int64_t>(output.size()) &&
127 llvm::all_of(
128 llvm::zip(yieldOp.getOperands(), output),
129 [](auto pair) {
130 return std::get<0>(pair).getType() ==
131 std::get<1>(pair).getType();
132 });
133 }) &&
134 "each scf.yield operand count and types must match output");
135 rewriter.setInsertionPointToEnd(entryBlock);
136 YieldOp::create(rewriter, loc, exeRegion.getResults());
137 }
138
139 return computeRegion;
140}
141
144 GPUParallelDimAttr parDim) {
145 return llvm::lower_bound(
146 parDims, parDim,
147 [](const GPUParallelDimAttr &lhs, const GPUParallelDimAttr &rhs) {
148 return lhs.getOrder() > rhs.getOrder();
149 });
150}
151
153 GPUParallelDimAttr parDim) {
155 if (lb == parDims.end() || *lb != parDim)
156 parDims.insert(lb, parDim);
157}
158
160 GPUParallelDimAttr parDim) {
162 if (lb != parDims.end() && *lb == parDim)
163 parDims.erase(lb);
164}
165
166#define ACC_OP_WITH_PAR_DIMS_LIST \
167 PrivatizeOp, ReductionAccumulateOp, ReductionAccumulateArrayOp, \
168 ReductionCombineOp
169
170GPUParallelDimsAttr getParDimsAttr(Operation *op) {
173 [](auto parOp) { return parOp.getParDimsAttr(); })
174 .Default([](Operation *op) -> GPUParallelDimsAttr {
175 if (Attribute attr = op->getAttr(GPUParallelDimsAttr::name)) {
176 GPUParallelDimsAttr parDimsAttr = dyn_cast<GPUParallelDimsAttr>(attr);
177 assert(parDimsAttr && "acc.par_dims must be a GPUParallelDimsAttr");
178 return parDimsAttr;
179 }
180 return nullptr;
181 });
182}
183
184bool hasParDimsAttr(Operation *op) { return getParDimsAttr(op) != nullptr; }
185
187 if (GPUParallelDimsAttr parDimsAttr = getParDimsAttr(op))
188 return parDimsAttr.isSeq();
189 return false;
190}
191
192void setParDimsAttr(Operation *op, GPUParallelDimsAttr attr) {
193 assert(!hasParDimsAttr(op) && "parallel dimensions attribute is already set");
196 [&](auto parOp) { parOp.setParDimsAttr(attr); })
197 .Default(
198 [&](Operation *op) { op->setAttr(GPUParallelDimsAttr::name, attr); });
199}
200
201void updateParDimsAttr(Operation *op, GPUParallelDimsAttr attr) {
202 assert(hasParDimsAttr(op) &&
203 "expected parallel dimensions attribute to already be set");
206 [&](auto parOp) { parOp.setParDimsAttr(attr); })
207 .Default(
208 [&](Operation *op) { op->setAttr(GPUParallelDimsAttr::name, attr); });
209}
210
211#undef ACC_OP_WITH_PAR_DIMS_LIST
212
214 return op->hasAttrOfType<GPUBlockRedundantAttr>(GPUBlockRedundantAttr::name);
215}
216
218 op->setAttr(GPUBlockRedundantAttr::name,
219 GPUBlockRedundantAttr::get(op->getContext()));
220}
221
223 assert(hasParDimsAttr(from) &&
224 "expected parallel dimensions attribute to already be set");
226}
227
228ActiveParDimsAttr getActiveParDimsAttr(Operation *op) {
229 return op->getAttrOfType<ActiveParDimsAttr>(ActiveParDimsAttr::name);
230}
231
233 return getActiveParDimsAttr(op) != nullptr;
234}
235
236void setActiveParDimsAttr(Operation *op, ActiveParDimsAttr attr) {
237 op->setAttr(ActiveParDimsAttr::name, attr);
238}
239
241 setActiveParDimsAttr(op, ActiveParDimsAttr::get(op->getContext(), dims));
242}
243
245 assert(alignment > 0 && llvm::isPowerOf2_64(alignment) &&
246 "alignment must be a power of two");
247 return (offset + alignment - 1) & ~(alignment - 1);
248}
249
251 int64_t aligned = alignOffset(bytesUsed_, alignment);
252 if (aligned + bytes > maxTotalBytes_) {
253 return false;
254 }
255 bytesUsed_ = aligned + bytes;
256 return true;
257}
258
260 int64_t total = 0;
261 region.walk([&](GPUSharedMemoryOp op) {
262 int64_t upperBound = op.getStaticUpperBoundBytes();
263 total = SharedMemoryBudget::alignOffset(total) + upperBound;
264 });
265 return total;
266}
267
268PrivatizeOp getPrivatizeOp(PrivateLocalOp privateLocal,
269 ComputeRegionOp computeRegion) {
270 Value value = privateLocal.getPrivatized();
271 if (BlockArgument blockArg = dyn_cast<BlockArgument>(value)) {
272 auto owner = dyn_cast<ComputeRegionOp>(blockArg.getOwner()->getParentOp());
273 value = (owner ? owner : computeRegion).getOperand(blockArg);
274 }
275 PrivatizeOp privatizeOp = value.getDefiningOp<PrivatizeOp>();
276 assert(privatizeOp && "expected privatize op to be the defining op");
277 return privatizeOp;
278}
279
280static bool isThreadXPrivatize(PrivatizeOp privatize) {
281 if (GPUParallelDimsAttr parDimsAttr = privatize.getParDimsAttr())
282 return llvm::any_of(parDimsAttr.getArray(),
283 [](GPUParallelDimAttr d) { return d.isThreadX(); });
284 return false;
285}
286
287MemRefType getPrivateBaseMemRefType(Type baseTy, ModuleOp module) {
288 auto memrefTy = cast<PointerLikeType>(baseTy).getAsMemRefType(module);
289 assert(memrefTy && "private base type must be convertible to memref");
290 return memrefTy;
291}
292
294collectPrivateLocalParDims(PrivateLocalOp privateLocal,
295 ComputeRegionOp computeRegion) {
297 // Walk the enclosing scf.parallel loops, but stop at the compute region
298 // boundary: loops outside the compute region do not contribute parallel
299 // dimensions to this privatization.
300 auto parentLoop = privateLocal->getParentOfType<scf::ParallelOp>();
301 while (parentLoop && computeRegion->isProperAncestor(parentLoop)) {
302 if (GPUParallelDimsAttr parDimsAttr = getParDimsAttr(parentLoop))
303 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
304 insertParDim(parDims, parDim);
305 parentLoop = parentLoop->getParentOfType<scf::ParallelOp>();
306 }
307 if (GPUParallelDimsAttr parDimsAttr = getParDimsAttr(computeRegion))
308 for (GPUParallelDimAttr parDim : parDimsAttr.getArray())
309 insertParDim(parDims, parDim);
310 if (parDims.empty()) {
311 for (GPUParallelDimAttr parDim : computeRegion.getLaunchParDims()) {
312 if (parDim.isAnyBlock())
313 insertParDim(parDims, parDim);
314 }
315 }
316
317 for (Operation *user : privateLocal.getResult().getUsers()) {
318 if (auto accumulateOp = dyn_cast<ReductionAccumulateOp>(user)) {
319 if (accumulateOp.getMemref() == privateLocal.getResult())
320 for (GPUParallelDimAttr parDim : accumulateOp.getParDims().getArray())
321 insertParDim(parDims, parDim);
322 }
323 if (auto combineOp = dyn_cast<ReductionCombineOp>(user)) {
324 if (combineOp.getSrcMemref() == privateLocal.getResult())
325 for (GPUParallelDimAttr parDim : getReductionCombineParDims(combineOp))
326 insertParDim(parDims, parDim);
327 }
328 if (auto combineRegionOp = dyn_cast<ReductionCombineRegionOp>(user)) {
329 if (combineRegionOp.getSrcVar() == privateLocal.getResult())
330 for (GPUParallelDimAttr parDim :
331 getReductionCombineParDims(combineRegionOp))
332 insertParDim(parDims, parDim);
333 }
334 }
335 return parDims;
336}
337
338static FailureOr<std::optional<int64_t>> getWorkerPrivateSharedMemoryNumCopies(
339 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion,
340 bool isWorkerPrivate, OpenACCSupport *support) {
341 if (!isWorkerPrivate)
342 return std::optional<int64_t>(1);
343
344 GPUParallelDimAttr threadY =
345 GPUParallelDimAttr::threadYDim(privateLocal.getContext());
346 std::optional<Value> workerArg = computeRegion.getKnownLaunchArg(threadY);
347 if (!workerArg)
348 return std::optional<int64_t>();
349
350 auto workerArgConst = workerArg->getDefiningOp<arith::ConstantIndexOp>();
351 if (workerArgConst)
352 return std::optional<int64_t>(workerArgConst.value());
353
354 FailureOr<int64_t> workerArgBound =
356 *workerArg);
357 if (succeeded(workerArgBound))
358 return std::optional<int64_t>(*workerArgBound);
359
360 if (support) {
361 (void)support->emitNYI(privateLocal.getLoc(),
362 "worker-private variables in shared memory "
363 "require compile-time constant num_workers");
364 return failure();
365 }
366 return std::optional<int64_t>();
367}
368
370 auto funcOp = op->getParentOfType<FunctionOpInterface>();
371 return funcOp && isSpecializedAccRoutine(funcOp);
372}
373
375 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
376 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support) {
377 if (isInsideACCSpecializedRoutine(computeRegion))
378 return false;
379
380 if (isThreadXPrivatize(getPrivatizeOp(privateLocal, computeRegion)))
381 return false;
382
383 bool isReductionAccumulator =
384 llvm::any_of(privateLocal.getResult().getUsers(), [](Operation *user) {
385 return isa<ReductionAccumulateOp>(user);
386 });
387
389 collectPrivateLocalParDims(privateLocal, computeRegion);
390 bool isGangPrivate =
391 llvm::any_of(parDims, [&](auto parDim) { return policy.isGang(parDim); });
392 bool isWorkerPrivate = llvm::any_of(
393 parDims, [&](auto parDim) { return policy.isWorker(parDim); });
394 bool isVectorPrivate = llvm::any_of(
395 parDims, [&](auto parDim) { return policy.isVector(parDim); });
396
397 auto baseTy = getPrivateBaseMemRefType(
398 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
399 module);
400
401 bool isBlockLevelPrivate =
402 !isVectorPrivate &&
403 (isGangPrivate ||
404 (isWorkerPrivate && baseTy.getRank() > 0 && !isReductionAccumulator));
405 if (!isBlockLevelPrivate)
406 return false;
407
408 for (int64_t dim : baseTy.getShape())
409 if (dim == ShapedType::kDynamic)
410 return false;
411
412 auto resultMemRefTy = dyn_cast<MemRefType>(privateLocal.getType());
413 if (!resultMemRefTy || !resultMemRefTy.getLayout().isIdentity() ||
414 resultMemRefTy.getMemorySpace())
415 return false;
416
417 if (isGangPrivate && isWorkerPrivate && !isReductionAccumulator)
418 return false;
419
420 FailureOr<std::optional<int64_t>> numCopies =
421 getWorkerPrivateSharedMemoryNumCopies(privateLocal, computeRegion,
422 isWorkerPrivate, support);
423 if (failed(numCopies))
424 return failure();
425 return numCopies->has_value();
426}
427
429 PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module,
430 const ACCToGPUMappingPolicy &policy, OpenACCSupport *support) {
431 FailureOr<bool> isCandidate = isPrivateLocalSharedMemoryCandidate(
432 privateLocal, computeRegion, module, policy);
433 if (failed(isCandidate) || !*isCandidate)
434 return std::nullopt;
435
437 collectPrivateLocalParDims(privateLocal, computeRegion);
438 bool isWorkerPrivate = llvm::any_of(
439 parDims, [&](auto parDim) { return policy.isWorker(parDim); });
440
441 FailureOr<std::optional<int64_t>> numCopies =
443 privateLocal, computeRegion, isWorkerPrivate, /*support=*/nullptr);
444 if (failed(numCopies) || !numCopies->has_value())
445 return std::nullopt;
446
447 auto baseTy = getPrivateBaseMemRefType(
448 cast<PrivateType>(privateLocal.getPrivatized().getType()).getBaseTy(),
449 module);
450 std::optional<TypeSizeAndAlignment> elementSizeAndAlignment =
451 getTypeSizeAndAlignment(baseTy.getElementType(), module, support);
452 if (!elementSizeAndAlignment)
453 return std::nullopt;
454
455 int64_t numElements = 1;
456 for (int64_t dim : baseTy.getShape())
457 numElements *= dim;
458 return elementSizeAndAlignment->first.getFixedValue() * numElements *
459 numCopies->value();
460}
461
462} // namespace acc
463} // namespace mlir
lhs
#define ACC_OP_WITH_PAR_DIMS_LIST
Attributes are known-constant values of operations.
Definition Attributes.h:25
This class represents an argument of a Block.
Definition Value.h:306
Block represents an ordered list of Operations.
Definition Block.h:33
BlockArgument getArgument(unsigned i)
Definition Block.h:153
OpListType & getOperations()
Definition Block.h:161
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition Block.cpp:158
IndexType getIndexType()
Definition Builders.cpp:59
The main mechanism for performing data layout queries.
A symbol reference with a reference path containing a single element.
This is a utility class for mapping one set of IR entities to another.
Definition IRMapping.h:26
auto lookup(T from) const
Lookup a mapped value within the map.
Definition IRMapping.h:72
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
Definition IRMapping.h:30
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
RAII guard to reset the insertion point of the builder when destroyed.
Definition Builders.h:351
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.
Definition Builders.cpp:439
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
Definition Builders.cpp:571
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Definition Builders.h:434
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition Builders.h:439
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
AttrClass getAttrOfType(StringAttr name)
Definition Operation.h:595
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Definition Operation.h:579
bool hasAttrOfType(NameT &&name)
Definition Operation.h:620
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:432
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition Operation.h:251
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Definition Operation.h:255
void setAttr(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
Definition Operation.h:627
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:233
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Block & front()
Definition Region.h:65
BlockListType & getBlocks()
Definition Region.h:45
RetT walk(FnT &&callback)
Walk all nested operations, blocks or regions (including this region), depending on the type of callb...
Definition Region.h:312
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
static FailureOr< int64_t > computeConstantBound(presburger::BoundType type, const Variable &var, const StopConditionFn &stopCondition=nullptr, ValueBoundsOptions options={})
Compute a constant bound for the given variable.
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
user_range getUsers() const
Definition Value.h:218
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
virtual bool isWorker(ParDimAttrT attr) const =0
Check if the attribute represents worker parallelism.
virtual bool isVector(ParDimAttrT attr) const =0
Check if the attribute represents vector parallelism.
virtual bool isGang(ParDimAttrT attr) const =0
Check if the attribute represents gang parallelism (any gang dimension).
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
bool tryAllocate(int64_t bytes, int64_t alignment=kDefaultAlignmentBytes)
Reserve bytes, rounding the current offset up to alignment first.
static int64_t alignOffset(int64_t offset, int64_t alignment=kDefaultAlignmentBytes)
Round offset up to the next multiple of alignment, which must be a power of two.
Specialization of arith.constant op that returns an integer of index type.
Definition Arith.h:114
GPUParallelDimsAttr getParDimsAttr(Operation *op)
Obtain the parallel dimensions carried by op, if any.
std::optional< DataLayout > getDataLayout(Operation *op, bool allowDefault=true)
Get the data layout for an operation.
MemRefType getPrivateBaseMemRefType(Type baseTy, ModuleOp module)
Returns the ranked MemRef type used to allocate privatized storage.
SmallVector< GPUParallelDimAttr > getReductionCombineParDims(ReductionCombineOp op)
Returns the parallel dimensions that participate in op's combine step.
void setActiveParDimsAttr(Operation *op, ActiveParDimsAttr attr)
Set active parallel dimensions on op.
void insertParDim(llvm::SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
Insert parDim into parDims while preserving dimension ordering.
bool hasActiveParDimsAttr(Operation *op)
Return whether op carries active parallel dimensions.
bool hasParDimsAttr(Operation *op)
Return whether op carries parallel dimensions.
ComputeRegionOp buildComputeRegion(Location loc, ValueRange launchArgs, ValueRange inputArgs, llvm::StringRef origin, Region &regionToClone, 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.
void setGPUBlockRedundantAttr(Operation *op)
Mark op with the acc.gpu_block_redundant attribute.
static FailureOr< std::optional< int64_t > > getWorkerPrivateSharedMemoryNumCopies(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, bool isWorkerPrivate, OpenACCSupport *support)
bool isSpecializedAccRoutine(mlir::Operation *op)
Used to check whether this is a specialized accelerator version of acc routine function.
Definition OpenACC.h:201
static bool isInsideACCSpecializedRoutine(Operation *op)
std::optional< TypeSizeAndAlignment > getTypeSizeAndAlignment(Type ty, ModuleOp module, const DataLayout &dl, OpenACCSupport *support=nullptr)
Returns the size and ABI alignment in bytes.
FailureOr< bool > isPrivateLocalSharedMemoryCandidate(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module, const ACCToGPUMappingPolicy &policy, OpenACCSupport *support=nullptr)
True when privateLocal may be placed in shared memory.
int64_t sumExistingSharedMemoryBytes(Region &region)
Sum aligned static_upper_bound_bytes for all acc.gpu_shared_memory in region.
scf::ExecuteRegionOp wrapMultiBlockRegionWithSCFExecuteRegion(Region &region, IRMapping &mapping, Location loc, RewriterBase &rewriter)
Wrap a multi-block region in an scf.execute_region.
void updateParDimsAttr(Operation *op, GPUParallelDimsAttr attr)
Update parallel dimensions on op.
PrivatizeOp getPrivatizeOp(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion)
Resolve the acc.privatize operation associated with a private local.
bool hasSeqParDims(Operation *op)
Return whether op carries sequential parallel dimensions.
void copyParDimsAttr(Operation *from, Operation *to)
Copy parallel dimensions from from to to.
bool hasGPUBlockRedundantAttr(Operation *op)
Return whether op is marked with the acc.gpu_block_redundant attribute, i.e.
void removeParDim(llvm::SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
Remove parDim from parDims if present.
void setParDimsAttr(Operation *op, GPUParallelDimsAttr attr)
Set parallel dimensions on op.
ActiveParDimsAttr getActiveParDimsAttr(Operation *op)
Obtain the active parallel dimensions carried by op, if any.
std::optional< int64_t > getPrivateLocalSharedMemoryUpperBoundBytes(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion, ModuleOp module, const ACCToGPUMappingPolicy &policy, OpenACCSupport *support=nullptr)
Upper-bound byte size for a shared-memory private_local candidate, or std::nullopt when not eligible ...
static bool isThreadXPrivatize(PrivatizeOp privatize)
static SmallVector< GPUParallelDimAttr >::iterator findParDim(SmallVector< GPUParallelDimAttr > &parDims, GPUParallelDimAttr parDim)
SmallVector< GPUParallelDimAttr > collectPrivateLocalParDims(PrivateLocalOp privateLocal, ComputeRegionOp computeRegion)
Collect parallel dimensions that govern privatization of privateLocal.
ACCParMappingPolicy< mlir::acc::GPUParallelDimAttr > ACCToGPUMappingPolicy
Type alias for the GPU-specific mapping policy.
Include the generated interface declarations.