18 #include "llvm/Support/Debug.h"
23 #define DEBUG_TYPE "decompose-affine-ops"
24 #define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE "]: ")
25 #define DBGSNL() (llvm::dbgs() << "\n")
33 while (
auto loopOp = currentOp->
getParentOfType<LoopLikeOpInterface>()) {
34 if (!loopOp.isDefinedOutsideOfLoop(operand.
get()))
45 llvm::map_range(op->getOpOperands(), [&](
OpOperand &operand) {
46 return numEnclosingInvariantLoops(operand);
49 int64_t numOperands = op.getNumOperands();
51 llvm::to_vector(llvm::seq<int64_t>(0, numOperands));
52 llvm::stable_sort(operandPositions, [&numInvariant](
size_t i1,
size_t i2) {
53 return numInvariant[i1] > numInvariant[i2];
58 for (int64_t i = 0; i < numOperands; ++i) {
59 operands[i] = op.getOperand(operandPositions[i]);
76 op->setOperands(operands);
89 auto rhsMap =
AffineMap::get(m.getNumDims(), m.getNumSymbols(), expr, ctx);
92 return rewriter.
create<AffineApplyOp>(originalOp.getLoc(), rhsMap,
101 if (m.getNumDims() > 0)
105 auto binExpr = dyn_cast<AffineBinaryOpExpr>(remainingExp);
109 if (!isa<AffineBinaryOpExpr>(binExpr.getLHS()) &&
110 !isa<AffineBinaryOpExpr>(binExpr.getRHS()))
117 op,
"only add or mul binary expr can be reassociated");
119 LLVM_DEBUG(
DBGS() <<
"Start decomposeIntoFinerGrainedOps: " << op <<
"\n");
126 auto currentBinExpr = dyn_cast<AffineBinaryOpExpr>(remainingExp);
127 if (!currentBinExpr || currentBinExpr.getKind() != binExpr.getKind()) {
128 subExpressions.push_back(remainingExp);
129 LLVM_DEBUG(
DBGS() <<
"--terminal: " << subExpressions.back() <<
"\n");
132 subExpressions.push_back(currentBinExpr.getRHS());
133 LLVM_DEBUG(
DBGS() <<
"--subExpr: " << subExpressions.back() <<
"\n");
134 remainingExp = currentBinExpr.getLHS();
141 auto getMaxSymbol = [&](
AffineExpr e) -> int64_t {
142 for (int64_t i = m.getNumSymbols(); i >= 0; --i)
143 if (e.isFunctionOfSymbol(i))
148 return getMaxSymbol(e1) < getMaxSymbol(e2);
151 llvm::interleaveComma(subExpressions,
DBGS() <<
"--sorted subexprs: ");
152 llvm::dbgs() <<
"\n");
162 for (int64_t i = 1, e = subExpressions.size(); i < e; ++i) {
164 current = rewriter.
create<AffineApplyOp>(op.getLoc(), binMap,
166 LLVM_DEBUG(
DBGS() <<
"--reassociate into: " << current <<
"\n");
170 rewriter.
replaceOp(op, current.getResult());
static AffineApplyOp createSubApply(RewriterBase &rewriter, AffineApplyOp originalOp, AffineExpr expr)
Build an affine.apply that is a subexpression expr of originalOps affine map and with the same operan...
Base type for affine expression.
MLIRContext * getContext() const
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
unsigned getNumDims() const
AffineMap replaceDimsAndSymbols(ArrayRef< AffineExpr > dimReplacements, ArrayRef< AffineExpr > symReplacements, unsigned numResultDims, unsigned numResultSyms) const
This method substitutes any uses of dimensions and symbols (e.g.
AffineExpr getResult(unsigned idx) const
IRValueT get() const
Return the current value being used by this operand.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class represents an operand of an operation.
Operation is the basic unit of execution within MLIR.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void finalizeOpModification(Operation *op)
This method is used to signal the end of an in-place modification of the given operation.
virtual void startOpModification(Operation *op)
This method is used to notify the rewriter that an in-place operation modification is about to happen...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getOwner() const
Return the owner of this operand.
void canonicalizeMapAndOperands(AffineMap *map, SmallVectorImpl< Value > *operands)
Modifies both map and operands in-place so as to:
FailureOr< AffineApplyOp > decompose(RewriterBase &rewriter, AffineApplyOp op)
Split an "affine.apply" operation into smaller ops.
int64_t numEnclosingInvariantLoops(OpOperand &operand)
Count the number of loops surrounding operand such that operand could be hoisted above.
void reorderOperandsByHoistability(RewriterBase &rewriter, AffineApplyOp op)
Helper function to rewrite op's affine map and reorder its operands such that they are in increasing ...
Include the generated interface declarations.
@ Mul
RHS of mul is always a constant or a symbolic expression.
AffineExpr getAffineBinaryOpExpr(AffineExprKind kind, AffineExpr lhs, AffineExpr rhs)
AffineExpr simplifyAffineExpr(AffineExpr expr, unsigned numDims, unsigned numSymbols)
Simplify an affine expression by flattening and some amount of simple analysis.
AffineExpr getAffineSymbolExpr(unsigned position, MLIRContext *context)