41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/SmallVector.h"
43#include "llvm/ADT/TypeSwitch.h"
44#include "llvm/Support/DebugLog.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/InterleavedRange.h"
47#include "llvm/Support/LogicalResult.h"
56#define DEBUG_TYPE "gpu-transforms"
62void transform::ApplyGPUToNVVMConversionPatternsOp::populatePatterns(
72transform::ApplyGPUToNVVMConversionPatternsOp::verifyTypeConverter(
73 transform::TypeConverterBuilderOpInterface builder) {
74 if (builder.getTypeConverterType() !=
"LLVMTypeConverter")
75 return emitOpError(
"expected LLVMTypeConverter");
79void transform::ApplyGPUWwmaToNVVMConversionPatternsOp::populatePatterns(
86transform::ApplyGPUWwmaToNVVMConversionPatternsOp::verifyTypeConverter(
87 transform::TypeConverterBuilderOpInterface builder) {
88 if (builder.getTypeConverterType() !=
"LLVMTypeConverter")
89 return emitOpError(
"expected LLVMTypeConverter");
93void transform::ApplyGPUSubgroupReduceToNVVMConversionPatternsOp::
100LogicalResult transform::ApplyGPUSubgroupReduceToNVVMConversionPatternsOp::
101 verifyTypeConverter(transform::TypeConverterBuilderOpInterface builder) {
102 if (builder.getTypeConverterType() !=
"LLVMTypeConverter")
103 return emitOpError(
"expected LLVMTypeConverter");
107void transform::ApplyGPUToROCDLConversionPatternsOp::populatePatterns(
112 FailureOr<ROCDL::TargetInfo> targetInfo =
114 assert(llvm::succeeded(targetInfo) &&
"verifier accepted this target");
120transform::ApplyGPUToROCDLConversionPatternsOp::verifyTypeConverter(
121 transform::TypeConverterBuilderOpInterface builder) {
123 [&] {
return emitOpError(); })))
125 if (builder.getTypeConverterType() !=
"LLVMTypeConverter")
126 return emitOpError(
"expected LLVMTypeConverter");
138void transform::ApplyGPUPromoteShuffleToAMDGPUPatternsOp::populatePatterns(
140 std::optional<StringRef> archName = getArch();
141 std::optional<ROCDL::TargetInfo> targetInfo;
145 assert(llvm::succeeded(parsed) &&
"verifier accepted this target");
146 targetInfo = *parsed;
152LogicalResult transform::ApplyGPUPromoteShuffleToAMDGPUPatternsOp::verify() {
153 std::optional<StringRef> archName = getArch();
158 [&] {
return emitOpError(); })))
169static std::optional<SmallVector<int64_t>>
173 for (
auto [
index, iter] : llvm::enumerate(
contract.getIteratorTypes())) {
175 order.push_back(
index);
179 llvm::SmallDenseSet<int64_t> dims;
181 dims.insert(cast<AffineDimExpr>(expr).getPosition());
184 for (
auto [
index, iter] : llvm::enumerate(
contract.getIteratorTypes())) {
186 order.push_back(
index);
190 for (
auto [
index, iter] : llvm::enumerate(
contract.getIteratorTypes())) {
192 order.push_back(
index);
200static std::optional<SmallVector<int64_t>>
202 if (
auto contract = dyn_cast<vector::ContractionOp>(op)) {
204 if (contractRank < 3)
207 nativeSize.append({m, n, k});
210 if (
auto writeOp = dyn_cast<vector::TransferWriteOp>(op)) {
211 int64_t writeRank = writeOp.getVectorType().getRank();
215 nativeSize.append({m, n});
218 if (
auto readOp = dyn_cast<vector::TransferReadOp>(op)) {
221 VectorType sliceType;
223 auto extract = dyn_cast<vector::ExtractStridedSliceOp>(users);
226 auto vecType = cast<VectorType>(extract.getResult().getType());
227 if (sliceType && sliceType != vecType)
231 return llvm::to_vector(sliceType.getShape());
234 if (
auto vecType = dyn_cast<VectorType>(op->
getResultTypes()[0])) {
237 if (vecType.getRank() < 2)
244 VectorType sliceType;
246 auto extract = dyn_cast<vector::ExtractStridedSliceOp>(users);
249 auto vecType = cast<VectorType>(extract.getResult().getType());
250 if (sliceType && sliceType != vecType)
255 return llvm::to_vector(sliceType.getShape());
260 nativeSize.append({m, n});
267void transform::ApplyUnrollVectorsSubgroupMmaOp::populatePatterns(
270 auto contract = dyn_cast<vector::ContractionOp>(op);
283 vector::populateVectorUnrollPatterns(
285 .setNativeShapeFn(nativeShapeFn)
286 .setUnrollTraversalOrderFn(unrollOrder));
303struct MappingKind {};
304struct BlockMappingKind : MappingKind {};
305struct ThreadMappingKind : MappingKind {};
311 if (transformOp.has_value())
312 return transformOp->emitDefiniteFailure() << message;
317template <
typename MappingKindType>
320 scf::ForallOp forallOp) {
321 if (!forallOp.getMapping().has_value()) {
323 "scf.forall op requires a mapping attribute");
326 bool hasBlockMapping = llvm::any_of(forallOp.getMapping().value(),
327 llvm::IsaPred<GPUBlockMappingAttr>);
328 bool hasWarpgroupMapping = llvm::any_of(
329 forallOp.getMapping().value(), llvm::IsaPred<GPUWarpgroupMappingAttr>);
330 bool hasWarpMapping = llvm::any_of(forallOp.getMapping().value(),
331 llvm::IsaPred<GPUWarpMappingAttr>);
332 bool hasThreadMapping = llvm::any_of(forallOp.getMapping().value(),
333 llvm::IsaPred<GPUThreadMappingAttr>);
334 bool hasLaneMapping = llvm::any_of(forallOp.getMapping().value(),
335 llvm::IsaPred<GPULaneMappingAttr>);
337 countMappingTypes += hasBlockMapping ? 1 : 0;
338 countMappingTypes += hasWarpgroupMapping ? 1 : 0;
339 countMappingTypes += hasWarpMapping ? 1 : 0;
340 countMappingTypes += hasThreadMapping ? 1 : 0;
341 countMappingTypes += hasLaneMapping ? 1 : 0;
342 if (countMappingTypes > 1) {
344 transformOp, forallOp,
345 "cannot mix different mapping types, use nesting");
347 if (std::is_same<MappingKindType, BlockMappingKind>::value &&
350 transformOp, forallOp,
351 "scf.forall op requires a mapping attribute of kind 'block'");
353 if (std::is_same<MappingKindType, ThreadMappingKind>::value &&
354 !hasLaneMapping && !hasThreadMapping && !hasWarpMapping &&
355 !hasWarpgroupMapping) {
357 "scf.forall op requires a mapping attribute "
358 "of kind 'thread' or 'warp'");
362 for (
Attribute map : forallOp.getMapping()->getValue()) {
363 if (seen.contains(map)) {
365 transformOp, forallOp,
366 "duplicate attribute, cannot map different loops "
367 "to the same mapping id");
372 auto isLinear = [](DeviceMappingAttrInterface attr) {
373 return attr.isLinearMapping();
375 if (llvm::any_of(forallOp.getDeviceMappingAttrs(), isLinear) &&
376 !llvm::all_of(forallOp.getDeviceMappingAttrs(), isLinear)) {
378 transformOp, forallOp,
379 "cannot mix linear and non-linear mapping modes");
382 FailureOr<DeviceMaskingAttrInterface> maybeMaskingAttr =
383 forallOp.getDeviceMaskingAttr();
384 if (succeeded(maybeMaskingAttr) && *maybeMaskingAttr &&
385 !forallOp.usesLinearMapping()) {
387 transformOp, forallOp,
388 "device masking is only available in linear mapping mode");
394template <
typename MappingKindType>
397 scf::ForallOp forallOp) {
405 if (!forallOp.isNormalized())
407 "unsupported non-normalized loops");
408 if (forallOp.getNumResults() > 0)
410 "only bufferized scf.forall can be mapped");
411 bool useLinearMapping = forallOp.usesLinearMapping();
414 int64_t maxNumMappingsSupported =
415 useLinearMapping ? (getMaxEnumValForMappingId() -
416 static_cast<uint64_t
>(MappingId::DimZ))
418 if (forallOp.getRank() > maxNumMappingsSupported) {
420 "scf.forall with rank > ")
421 << maxNumMappingsSupported
422 <<
" does not lower for the specified mapping attribute type";
424 auto numParallelIterations =
426 if (!forallOp.isNormalized() || !numParallelIterations.has_value()) {
428 transformOp, forallOp,
429 "requires statically sized, normalized forall op");
441template <
typename OpTy,
typename OperationOrBlock>
446 parent->walk([&](OpTy idOp) {
447 if (availableMappingSizes[
static_cast<int64_t>(idOp.getDimension())] == 1)
453 RewriterBase &rewriter, std::optional<TransformOpInterface> transformOp,
456 LDBG() <<
"--start rewriteOneForallCommonImpl";
459 auto numParallelIterations =
461 assert(forallOp.isNormalized() && numParallelIterations.has_value() &&
462 "requires statically sized, normalized forall op");
465 forallOp.getDeviceMappingAttrs();
467 forallMappingAttrs.insert_range(forallMappingAttrsVec);
469 return cast<DeviceMappingAttrInterface>(a).getMappingId() <
470 cast<DeviceMappingAttrInterface>(
b).getMappingId();
476 DeviceMappingAttrInterface maxMapping = cast<DeviceMappingAttrInterface>(
477 *llvm::max_element(forallMappingAttrs, comparator));
478 DeviceMappingAttrInterface maxLinearMapping;
479 if (maxMapping.isLinearMapping())
480 maxLinearMapping = maxMapping;
483 if (maxLinearMapping && comparator(maxLinearMapping, attr))
486 if (!forallMappingAttrs.insert(attr))
489 tmpMappingSizes.push_back(1);
491 LDBG() <<
"----tmpMappingSizes extracted from scf.forall op: "
492 << llvm::interleaved(tmpMappingSizes);
496 forallMappingAttrs.getArrayRef(), tmpMappingSizes, comparator);
497 LDBG() <<
"----forallMappingSizes: " << llvm::interleaved(forallMappingSizes);
498 LDBG() <<
"----forallMappingAttrs: " << llvm::interleaved(forallMappingAttrs);
505 bool originalBasisWasProvided = !originalBasis.empty();
506 if (!originalBasisWasProvided) {
507 LDBG() <<
"----originalBasis was not provided, deriving it and there will "
510 originalBasis = forallMappingSizes;
511 while (originalBasis.size() < 3)
512 originalBasis.push_back(1);
514 LDBG() <<
"----originalBasis was provided, using it, there will be "
517 LDBG() <<
"------originalBasis: " << llvm::interleaved(originalBasis);
520 gpuIdBuilder.
idBuilder(rewriter, loc, forallMappingSizes, originalBasis);
521 if (!builderResult.
errorMsg.empty())
524 LDBG() << builderResult;
530 for (
auto [iv, dim] : llvm::zip_equal(
531 forallOp.getInductionVars(),
532 forallMappingAttrs.getArrayRef().take_front(forallOp.getRank()))) {
533 auto mappingAttr = cast<DeviceMappingAttrInterface>(dim);
534 Value peIdOp = mappingIdOps[mappingAttr.getRelativeIndex()];
535 LDBG() <<
"----map: " << iv <<
" to " << peIdOp;
543 if (originalBasisWasProvided) {
545 predicate = predicate ? arith::AndIOp::create(rewriter, loc, predicate,
553 rewriter.
eraseOp(forallOp.getTerminator());
558 auto ifOp = scf::IfOp::create(rewriter, loc, predicate,
560 targetBlock = ifOp.thenBlock();
561 insertionPoint = ifOp.thenBlock()->
begin();
565 targetBlock = forallOp->getBlock();
568 Block &sourceBlock = forallOp.getRegion().
front();
573 for (
Value loopIndex : forallOp.getInductionVars()) {
581 LDBG() <<
"----result forallMappingSizes: "
582 << llvm::interleaved(forallMappingSizes);
583 LDBG() <<
"----result mappingIdOps: " << llvm::interleaved(mappingIdOps);
594 RewriterBase &rewriter, TransformOpInterface transformOp,
597 LDBG() <<
"Start mapForallToBlocksImpl";
605 if (!
diag.succeeded())
610 Block *parentBlock = forallOp->getBlock();
622 rewriter, transformOp, forallOp,
623 gridDims, rewriteResult, gpuIdBuilder);
627 if (!
diag.succeeded())
631 if (gridDims.empty()) {
633 while (gridDims.size() < 3)
634 gridDims.push_back(1);
636 assert(gridDims.size() == 3 &&
"Need 3-D gridDims");
648 scf::ForallOp &topLevelForallOp,
649 TransformOpInterface transformOp) {
650 auto walkResult =
target->walk([&](scf::ForallOp forallOp) {
651 if (forallOp->getParentOfType<scf::ForallOp>())
653 if (topLevelForallOp)
656 topLevelForallOp = forallOp;
660 if (walkResult.wasInterrupted() || !topLevelForallOp)
661 return transformOp.emitSilenceableError()
662 <<
"could not find a unique topLevel scf.forall";
669 LaunchOp gpuLaunch = dyn_cast<LaunchOp>(
target);
670 auto transformOp = cast<TransformOpInterface>(getOperation());
672 if (!getGenerateGpuLaunch() && !gpuLaunch) {
674 emitSilenceableError()
675 <<
"Given target is not gpu.launch, set `generate_gpu_launch` "
677 diag.attachNote(
target->getLoc()) <<
"when applied to this payload op";
681 scf::ForallOp topLevelForallOp;
683 target, topLevelForallOp, transformOp);
684 if (!
diag.succeeded()) {
685 diag.attachNote(
target->getLoc()) <<
"when applied to this payload op";
688 assert(topLevelForallOp &&
"expect an scf.forall");
691 if (!getGenerateGpuLaunch() && gridDims.size() != 3)
692 return transformOp.emitDefiniteFailure(
"transform require size-3 mapping");
698 if (getGenerateGpuLaunch()) {
701 if (!
diag.succeeded())
706 rewriter.
eraseOp(topLevelForallOp);
707 topLevelForallOp = cast<scf::ForallOp>(newForallOp);
711 bool useLinearMapping =
false;
712 if (topLevelForallOp.getMapping())
713 useLinearMapping = topLevelForallOp.usesLinearMapping();
715 FailureOr<DeviceMaskingAttrInterface> maybeMaskingAttr =
716 topLevelForallOp.getDeviceMaskingAttr();
717 assert(succeeded(maybeMaskingAttr) &&
"unexpected failed maybeMaskingAttr");
718 assert((!*maybeMaskingAttr || useLinearMapping) &&
719 "masking requires linear mapping");
725 rewriter, transformOp, topLevelForallOp, gridDims, gpuBlockIdBuilder);
726 if (!
diag.succeeded())
732 cast<TransformOpInterface>(getOperation()), gridDims[0],
733 gridDims[1], gridDims[2]);
739LogicalResult transform::MapForallToBlocks::verify() {
740 if (!getGridDims().empty() && getGridDims().size() != 3) {
741 return emitOpError() <<
"transform requires empty or size-3 grid_dims";
751 std::optional<TransformOpInterface> transformOp, scf::ForallOp forallOp,
753 int factor,
bool useLinearMapping =
false) {
754 if (llvm::any_of(blockOrGridSizes, [](
int64_t i) {
return i <= 0; })) {
756 "block/grid sizes must be strictly positive");
758 if (!useLinearMapping && blockOrGridSizes.front() % factor != 0) {
760 transformOp, forallOp,
761 Twine(
"3-D mapping: size of threadIdx.x must be a multiple of ") +
765 bool hasZeroParallelIteration =
766 llvm::any_of(numParallelIterations, [](
int64_t i) {
return i == 0; });
770 int64_t requiredResourceCount =
771 hasZeroParallelIteration ? 0
774 if (requiredResourceCount > availableResourceCount) {
776 transformOp, forallOp,
777 Twine(
"the number of required parallel resources (blocks or "
779 Twine(requiredResourceCount) +
780 " overflows the number of available resources " +
781 Twine(availableResourceCount));
791 DeviceMappingAttrInterface mappingAttr =
792 forallOp.getDeviceMappingAttrs().front();
793 bool useLinearMapping = mappingAttr.isLinearMapping();
796 auto numParallelIterations =
798 if (!forallOp.isNormalized() || !numParallelIterations.has_value()) {
800 transformOp, forallOp,
801 "requires statically sized, normalized forall op");
804 if (isa<GPUWarpgroupMappingAttr>(mappingAttr)) {
806 }
else if (isa<GPUWarpMappingAttr>(mappingAttr)) {
811 blockSizes, factor, useLinearMapping);
812 if (!
diag.succeeded())
815 FailureOr<DeviceMaskingAttrInterface> maybeMaskingAttr =
816 forallOp.getDeviceMaskingAttr();
817 assert(succeeded(maybeMaskingAttr) &&
"unexpected failed maybeMaskingAttr");
818 assert((!*maybeMaskingAttr || useLinearMapping) &&
819 "masking requires linear mapping");
825 .Case([&](GPUWarpgroupMappingAttr) {
829 .Case([&](GPUWarpMappingAttr) {
833 .Case([&](GPUThreadMappingAttr) {
836 .Case([&](GPULaneMappingAttr) {
840 .DefaultUnreachable(
"unknown mapping attribute");
845 RewriterBase &rewriter, std::optional<TransformOpInterface> transformOp,
847 bool syncAfterDistribute) {
855 if (!
diag.succeeded())
863 transformOp, forallOp, blockSizes, warpSize, gpuIdBuilder);
864 if (!
diag.succeeded())
874 rewriter, transformOp, forallOp, blockSizes, rewriteResult, gpuIdBuilder);
875 if (!
diag.succeeded())
878 if (syncAfterDistribute)
879 BarrierOp::create(rewriter, loc);
885 RewriterBase &rewriter, std::optional<TransformOpInterface> transformOp,
887 bool syncAfterDistribute) {
888 LDBG() <<
"Start mapNestedForallToThreadsImpl";
889 if (blockDims.size() != 3) {
891 "requires size-3 thread mapping");
900 rewriter, transformOp, forallOp, blockDims, warpSize,
901 syncAfterDistribute);
902 if (
diag.isDefiniteFailure())
904 if (
diag.succeeded())
922 LaunchOp gpuLaunch = dyn_cast<LaunchOp>(
target);
923 auto transformOp = cast<TransformOpInterface>(getOperation());
927 return emitSilenceableError() <<
"Given target is not a gpu.launch";
932 checkGpuLimits(transformOp, std::nullopt, std::nullopt, std::nullopt,
933 blockDims[0], blockDims[1], blockDims[2]);
934 if (
diag.isSilenceableFailure()) {
935 diag.attachNote(getLoc()) << getBlockDimsAttrName() <<
" is too large";
942 std::nullopt, std::nullopt, blockDims[0], blockDims[1],
948 getWarpSize(), getSyncAfterDistribute());
950 results.
push_back(gpuLaunch.getOperation());
961class GPUTransformDialectExtension
963 GPUTransformDialectExtension> {
967 GPUTransformDialectExtension() {
968 declareGeneratedDialect<GPUDialect>();
969 declareGeneratedDialect<amdgpu::AMDGPUDialect>();
970 declareGeneratedDialect<arith::ArithDialect>();
971 declareGeneratedDialect<scf::SCFDialect>();
972 registerTransformOps<
974#include "mlir/Dialect/GPU/TransformOps/GPUTransformOps.cpp.inc"
980#define GET_OP_CLASSES
981#include "mlir/Dialect/GPU/TransformOps/GPUTransformOps.cpp.inc"
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
#define MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CLASS_NAME)
Base type for affine expression.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
OpListType::iterator iterator
OpListType & getOperations()
The result of a transform IR operation application.
static DiagnosedSilenceableFailure success()
Constructs a DiagnosedSilenceableFailure in the success state.
bool succeeded() const
Returns true if this is a success.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtensions()
Add the given extensions to the registry.
This is a utility class for mapping one set of IR entities to another.
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'.
Conversion from types to the LLVM IR dialect.
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::iterator getInsertionPoint() const
Returns the current insertion point of the builder.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
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.
result_type_range getResultTypes()
user_range getUsers()
Returns a range of all users.
unsigned getNumResults()
Return the number of results held by this operation.
static FailureOr< TargetInfo > get(StringRef arch, unsigned waveSize=0, function_ref< InFlightDiagnostic()> emitError=nullptr)
Resolves a target description.
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.
virtual void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
Base class for extensions of the Transform dialect that supports injecting operations into the Transf...
bool hasElementwiseMappableTraits(Operation *op)
Together, Elementwise, Scalarizable, Vectorizable, and Tensorizable provide an easy way for scalar op...
void populateCommonGPUTypeAndAttributeConversions(TypeConverter &typeConverter)
Remap common GPU memory spaces (Workgroup, Private, etc) to LLVM address spaces.
void registerTransformDialectExtension(DialectRegistry ®istry)
uint64_t getN(LevelType lt)
uint64_t getM(LevelType lt)
bool isReductionIterator(Attribute attr)
Returns true if attr has "reduction" iterator type semantics.
bool isParallelIterator(Attribute attr)
Returns true if attr has "parallel" iterator type semantics.
Include the generated interface declarations.
void populateGpuPromoteShuffleToAMDGPUPatterns(RewritePatternSet &patterns, std::optional< ROCDL::TargetInfo > target)
Tries to promote gpu.shuffles to specialized AMDGPU intrinsics.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
void populateGpuRewritePatterns(RewritePatternSet &patterns)
Collect all patterns to rewrite ops within the GPU dialect.
void populateGpuToROCDLConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, gpu::amd::Runtime runtime, const ROCDL::TargetInfo &target)
Collect a set of patterns to convert from the GPU dialect to ROCDL.
int64_t computeProduct(ArrayRef< int64_t > basis)
Self-explicit.
llvm::SetVector< T, Vector, Set, N > SetVector
DiagnosedDefiniteFailure emitDefiniteFailure(Location loc, const Twine &message={})
Emits a definite failure with the given message.
void configureGpuToNVVMTypeConverter(LLVMTypeConverter &converter)
Configure the LLVM type convert to convert types and address spaces from the GPU dialect to NVVM.
void populateGpuSubgroupReduceOpLoweringPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Populate GpuSubgroupReduce pattern to NVVM.
void populateGpuToNVVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Collect a set of patterns to convert from the GPU dialect to NVVM.
llvm::TypeSwitch< T, ResultT > TypeSwitch
std::optional< SmallVector< int64_t > > getConstantIntValues(ArrayRef< OpFoldResult > ofrs)
If all ofrs are constant integers or IntegerAttrs, return the integers.
SmallVector< Value > getValuesSortedByKey(ArrayRef< Attribute > keys, ArrayRef< Value > values, llvm::function_ref< bool(Attribute, Attribute)> compare)
Helper to sort values according to matching keys.
void populateGpuEliminateBarriersPatterns(RewritePatternSet &patterns)
Erase barriers that do not enforce conflicting memory side effects.
void populateGpuWMMAToNVVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, PatternBenefit benefit=1)
Collect a set of patterns to convert WMMA ops from GPU dialect to NVVM.
Struct to return the result of the rewrite of a forall operation.
SmallVector< Value > mappingIds
SmallVector< int64_t > mappingSizes
Options that control the vector unrolling.