MLIR
21.0.0git
|
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/Affine/Analysis/AffineStructures.h"
#include "mlir/Dialect/Affine/Analysis/LoopAnalysis.h"
#include "mlir/Dialect/Affine/Analysis/Utils.h"
#include "mlir/Dialect/Affine/LoopFusionUtils.h"
#include "mlir/Dialect/Affine/LoopUtils.h"
#include "mlir/Dialect/Affine/Utils.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <iomanip>
#include <optional>
#include <sstream>
#include "mlir/Dialect/Affine/Passes.h.inc"
Go to the source code of this file.
Namespaces | |
mlir | |
Include the generated interface declarations. | |
mlir::affine | |
Macros | |
#define | GEN_PASS_DEF_AFFINELOOPFUSION |
#define | DEBUG_TYPE "affine-fusion" |
Functions | |
static bool | canRemoveSrcNodeAfterFusion (unsigned srcId, unsigned dstId, const ComputationSliceState &fusionSlice, Operation *fusedLoopInsPoint, const DenseSet< Value > &escapingMemRefs, const MemRefDependenceGraph &mdg) |
Returns true if node 'srcId' can be removed after fusing it with node 'dstId'. More... | |
static void | getProducerCandidates (unsigned dstId, const MemRefDependenceGraph &mdg, SmallVectorImpl< unsigned > &srcIdCandidates) |
Returns in 'srcIdCandidates' the producer fusion candidates for consumer 'dstId'. More... | |
static void | gatherProducerConsumerMemrefs (unsigned srcId, unsigned dstId, const MemRefDependenceGraph &mdg, DenseSet< Value > &producerConsumerMemrefs) |
Returns in 'producerConsumerMemrefs' the memrefs involved in a producer-consumer dependence between 'srcId' and 'dstId'. More... | |
static bool | isEscapingMemref (Value memref, Block *block) |
A memref escapes in the context of the fusion pass if either: More... | |
static void | gatherEscapingMemrefs (unsigned id, const MemRefDependenceGraph &mdg, DenseSet< Value > &escapingMemRefs) |
Returns in 'escapingMemRefs' the memrefs from affine store ops in node 'id' that escape the block or are accessed in a non-affine way. More... | |
static void | sinkSequentialLoops (MemRefDependenceGraph::Node *node) |
static Operation * | getDominanceFilterForPrivateMemRefRepl (Block *sliceInsertionBlock, ArrayRef< Operation * > producerStores) |
Get the operation that should act as a dominance filter while replacing memref uses with a private memref for which producerStores and sliceInsertionBlock are provided. More... | |
static std::optional< double > | getAdditionalComputeFraction (AffineForOp srcForOp, AffineForOp dstForOp, unsigned depth, ArrayRef< ComputationSliceState > depthSliceUnions, int64_t &sliceCost, int64_t &fusedLoopNestComputeCost) |
Returns the amount of additional (redundant) computation that will be done as a fraction of the total computation if srcForOp is fused into dstForOp at depth depth . More... | |
static Value | createPrivateMemRef (AffineForOp forOp, ArrayRef< Operation * > storeOps, unsigned dstLoopDepth, std::optional< unsigned > fastMemorySpace, Block *sliceInsertionBlock, uint64_t localBufSizeThreshold) |
static bool | isFusionProfitable (AffineForOp srcForOp, ArrayRef< Operation * > producerStores, AffineForOp dstForOp, ArrayRef< ComputationSliceState > depthSliceUnions, unsigned maxLegalFusionDepth, unsigned *dstLoopDepth, double computeToleranceThreshold) |
#define DEBUG_TYPE "affine-fusion" |
Definition at line 43 of file LoopFusion.cpp.
#define GEN_PASS_DEF_AFFINELOOPFUSION |
Definition at line 38 of file LoopFusion.cpp.
|
static |
Returns true if node 'srcId' can be removed after fusing it with node 'dstId'.
The node can be removed if any of the following conditions are met:
Definition at line 77 of file LoopFusion.cpp.
References mlir::Operation::getBlock(), mlir::affine::MemRefDependenceGraph::getNode(), mlir::Operation::isBeforeInBlock(), mlir::affine::ComputationSliceState::isMaximal(), mlir::affine::MemRefDependenceGraph::Node::op, and mlir::affine::MemRefDependenceGraph::outEdges.
|
static |
Definition at line 334 of file LoopFusion.cpp.
References mlir::affine::MemRefRegion::compute(), mlir::OpBuilder::create(), mlir::AffineMap::get(), mlir::get(), mlir::getAffineDimExpr(), mlir::affine::MemRefRegion::getConstantBoundingSizeAndShape(), mlir::affine::MemRefRegion::getConstraints(), getDominanceFilterForPrivateMemRefRepl(), mlir::Operation::getLoc(), mlir::affine::getMemRefIntOrFloatEltSizeInBytes(), mlir::presburger::IntegerRelation::getNumDimAndSymbolVars(), mlir::FlatLinearValueConstraints::getValues(), mlir::affine::replaceAllMemRefUsesWith(), and mlir::simplifyAffineExpr().
|
static |
Returns in 'escapingMemRefs' the memrefs from affine store ops in node 'id' that escape the block or are accessed in a non-affine way.
Definition at line 217 of file LoopFusion.cpp.
References mlir::affine::MemRefDependenceGraph::block, mlir::affine::MemRefDependenceGraph::getNode(), and isEscapingMemref().
|
static |
Returns in 'producerConsumerMemrefs' the memrefs involved in a producer-consumer dependence between 'srcId' and 'dstId'.
Definition at line 171 of file LoopFusion.cpp.
References mlir::affine::gatherProducerConsumerMemrefs(), and mlir::affine::MemRefDependenceGraph::getNode().
|
static |
Returns the amount of additional (redundant) computation that will be done as a fraction of the total computation if srcForOp
is fused into dstForOp
at depth depth
.
The method returns the compute cost of the slice and the fused nest's compute cost in the trailing output arguments.
Definition at line 280 of file LoopFusion.cpp.
References mlir::affine::getComputeCost(), mlir::affine::getFusionComputeCost(), mlir::affine::getLoopNestStats(), and mlir::affine::ComputationSliceState::isEmpty().
Referenced by isFusionProfitable().
|
static |
Get the operation that should act as a dominance filter while replacing memref uses with a private memref for which producerStores
and sliceInsertionBlock
are provided.
This effectively determines in what part of the IR we should be performing the replacement.
Definition at line 245 of file LoopFusion.cpp.
References mlir::Block::begin(), mlir::Block::findAncestorOpInBlock(), mlir::affine::findInnermostCommonBlockInScope(), and mlir::Operation::isBeforeInBlock().
Referenced by createPrivateMemRef().
|
static |
Returns in 'srcIdCandidates' the producer fusion candidates for consumer 'dstId'.
Candidates are sorted by node id order. This order corresponds to the program order when the 'mdg' is created. However, program order is not guaranteed and must not be required by the client. Program order won't be held if the 'mdg' is reused from a previous fusion step or if the node creation order changes in the future to support more advance cases.
Definition at line 136 of file LoopFusion.cpp.
References mlir::affine::MemRefDependenceGraph::getNode(), and mlir::affine::MemRefDependenceGraph::inEdges.
A memref escapes in the context of the fusion pass if either:
Definition at line 187 of file LoopFusion.cpp.
References mlir::Value::getDefiningOp(), and mlir::Value::getUsers().
Referenced by gatherEscapingMemrefs().
|
static |
Definition at line 498 of file LoopFusion.cpp.
References mlir::affine::MemRefRegion::compute(), getAdditionalComputeFraction(), mlir::affine::getComputeCost(), mlir::Operation::getLoc(), mlir::affine::getLoopNestStats(), mlir::affine::getMemoryFootprintBytes(), mlir::affine::MemRefRegion::getRegionSize(), mlir::affine::ComputationSliceState::isEmpty(), and max().
|
static |
Definition at line 234 of file LoopFusion.cpp.
References mlir::affine::MemRefDependenceGraph::Node::op, and mlir::affine::sinkSequentialLoops().