//===- AffineToStandard.cpp - Lower affine constructs to primitives -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file lowers affine constructs (If and For statements, AffineApply // operations) within a function into their standard If and For equivalent ops. // //===----------------------------------------------------------------------===// #include "mlir/Conversion/AffineToStandard/AffineToStandard.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/Transforms/Transforms.h" #include "mlir/Dialect/Affine/Utils.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/IR/IRMapping.h" #include "mlir/IR/IntegerSet.h" #include "mlir/IR/MLIRContext.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/Passes.h" namespace mlir { #define GEN_PASS_DEF_CONVERTAFFINETOSTANDARD #include "mlir/Conversion/Passes.h.inc" } // namespace mlir usingnamespacemlir; usingnamespacemlir::affine; usingnamespacemlir::vector; /// Given a range of values, emit the code that reduces them with "min" or "max" /// depending on the provided comparison predicate, sgt for max and slt for min. /// /// Multiple values are scanned in a linear sequence. This creates a data /// dependences that wouldn't exist in a tree reduction, but is easier to /// recognize as a reduction by the subsequent passes. static Value buildMinMaxReductionSeq(Location loc, arith::CmpIPredicate predicate, ValueRange values, OpBuilder &builder) { … } /// Emit instructions that correspond to computing the maximum value among the /// values of a (potentially) multi-output affine map applied to `operands`. static Value lowerAffineMapMax(OpBuilder &builder, Location loc, AffineMap map, ValueRange operands) { … } /// Emit instructions that correspond to computing the minimum value among the /// values of a (potentially) multi-output affine map applied to `operands`. static Value lowerAffineMapMin(OpBuilder &builder, Location loc, AffineMap map, ValueRange operands) { … } /// Emit instructions that correspond to the affine map in the upper bound /// applied to the respective operands, and compute the minimum value across /// the results. Value mlir::lowerAffineUpperBound(AffineForOp op, OpBuilder &builder) { … } /// Emit instructions that correspond to the affine map in the lower bound /// applied to the respective operands, and compute the maximum value across /// the results. Value mlir::lowerAffineLowerBound(AffineForOp op, OpBuilder &builder) { … } namespace { class AffineMinLowering : public OpRewritePattern<AffineMinOp> { … }; class AffineMaxLowering : public OpRewritePattern<AffineMaxOp> { … }; /// Affine yields ops are removed. class AffineYieldOpLowering : public OpRewritePattern<AffineYieldOp> { … }; class AffineForLowering : public OpRewritePattern<AffineForOp> { … }; /// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel` /// operation. class AffineParallelLowering : public OpRewritePattern<AffineParallelOp> { … }; class AffineIfLowering : public OpRewritePattern<AffineIfOp> { … }; /// Convert an "affine.apply" operation into a sequence of arithmetic /// operations using the StandardOps dialect. class AffineApplyLowering : public OpRewritePattern<AffineApplyOp> { … }; /// Apply the affine map from an 'affine.load' operation to its operands, and /// feed the results to a newly created 'memref.load' operation (which replaces /// the original 'affine.load'). class AffineLoadLowering : public OpRewritePattern<AffineLoadOp> { … }; /// Apply the affine map from an 'affine.prefetch' operation to its operands, /// and feed the results to a newly created 'memref.prefetch' operation (which /// replaces the original 'affine.prefetch'). class AffinePrefetchLowering : public OpRewritePattern<AffinePrefetchOp> { … }; /// Apply the affine map from an 'affine.store' operation to its operands, and /// feed the results to a newly created 'memref.store' operation (which replaces /// the original 'affine.store'). class AffineStoreLowering : public OpRewritePattern<AffineStoreOp> { … }; /// Apply the affine maps from an 'affine.dma_start' operation to each of their /// respective map operands, and feed the results to a newly created /// 'memref.dma_start' operation (which replaces the original /// 'affine.dma_start'). class AffineDmaStartLowering : public OpRewritePattern<AffineDmaStartOp> { … }; /// Apply the affine map from an 'affine.dma_wait' operation tag memref, /// and feed the results to a newly created 'memref.dma_wait' operation (which /// replaces the original 'affine.dma_wait'). class AffineDmaWaitLowering : public OpRewritePattern<AffineDmaWaitOp> { … }; /// Apply the affine map from an 'affine.vector_load' operation to its operands, /// and feed the results to a newly created 'vector.load' operation (which /// replaces the original 'affine.vector_load'). class AffineVectorLoadLowering : public OpRewritePattern<AffineVectorLoadOp> { … }; /// Apply the affine map from an 'affine.vector_store' operation to its /// operands, and feed the results to a newly created 'vector.store' operation /// (which replaces the original 'affine.vector_store'). class AffineVectorStoreLowering : public OpRewritePattern<AffineVectorStoreOp> { … }; } // namespace void mlir::populateAffineToStdConversionPatterns(RewritePatternSet &patterns) { … } void mlir::populateAffineToVectorConversionPatterns( RewritePatternSet &patterns) { … } namespace { class LowerAffinePass : public impl::ConvertAffineToStandardBase<LowerAffinePass> { … }; } // namespace /// Lowers If and For operations within a function into their lower level CFG /// equivalent blocks. std::unique_ptr<Pass> mlir::createLowerAffinePass() { … }