19#include "llvm/Support/DebugLog.h"
27 Block *insertionBlock) {
32 auto *parentOp = region->getParentOp();
34 !parentOp->getBlock())
38 auto *
interface = interfaces.getInterfaceFor(parentOp);
39 if (LLVM_UNLIKELY(interface && interface->shouldMaterializeInto(region)))
43 insertionBlock = parentOp->getBlock();
45 llvm_unreachable(
"expected valid insertion region");
74 *inPlaceUpdate =
false;
78 if (isFolderOwnedConstant(op)) {
82 if (&opBlock->
front() != op && !isFolderOwnedConstant(op->getPrevNode())) {
83 rewriter.moveOpBefore(op, &opBlock->
front());
84 op->
setLoc(erasedFoldedLocation);
91 if (failed(
tryToFold(op, results, maxIterations)))
95 if (results.empty()) {
97 *inPlaceUpdate =
true;
98 if (
auto *rewriteListener = dyn_cast_if_present<RewriterBase::Listener>(
99 rewriter.getListener())) {
101 rewriteListener->notifyOperationModified(op);
109 rewriter.replaceOp(op, results);
119 if (isFolderOwnedConstant(op)) {
120 if (&opBlock->
front() != op && !isFolderOwnedConstant(op->getPrevNode())) {
121 rewriter.moveOpBefore(op, &opBlock->
front());
122 op->
setLoc(erasedFoldedLocation);
131 assert(constValue &&
"expected `op` to be a constant");
138 expectedValue == constValue &&
139 "provided constant value was not the expected value of the constant");
145 auto &uniquedConstants = foldScopes[insertRegion];
146 Operation *&folderConstOp = uniquedConstants[std::make_tuple(
152 rewriter.replaceOp(op, folderConstOp->
getResults());
153 folderConstOp->
setLoc(erasedFoldedLocation);
164 if (opBlock != insertBlock) {
165 rewriter.moveOpBefore(op, &insertBlock->
front());
166 op->
setLoc(erasedFoldedLocation);
168 }
else if (&insertBlock->
front() != op &&
169 !isFolderOwnedConstant(op->getPrevNode())) {
170 rewriter.moveOpBefore(op, &insertBlock->
front());
175 referencedDialects[op].push_back(op->
getDialect());
183 auto it = referencedDialects.find(op);
184 if (it == referencedDialects.end())
194 auto &uniquedConstants =
199 for (
auto *dialect : it->second)
200 uniquedConstants.erase(std::make_tuple(dialect, constValue, type));
201 referencedDialects.erase(it);
207 referencedDialects.clear();
216 auto &entry = insertRegion->front();
217 rewriter.setInsertionPointToStart(&entry);
221 auto &uniquedConstants = foldScopes[insertRegion];
222 Operation *constOp = tryGetOrCreateConstant(uniquedConstants, dialect, value,
223 type, erasedFoldedLocation);
227bool OperationFolder::isFolderOwnedConstant(
Operation *op)
const {
228 return referencedDialects.count(op);
237 if (failed(op->
fold(foldResults)))
241 LDBG() <<
"Folded in place #" << count
243 }
while (count++ < maxIterations && foldResults.empty() &&
244 succeeded(op->
fold(foldResults)));
246 if (
failed(processFoldResults(op, results, foldResults)))
252OperationFolder::processFoldResults(
Operation *op,
256 if (foldResults.empty())
263 auto &entry = insertRegion->front();
264 rewriter.setInsertionPointToStart(&entry);
267 auto &uniquedConstants = foldScopes[insertRegion];
272 assert(!foldResults[i].isNull() &&
"expected valid OpFoldResult");
275 if (
auto repl = llvm::dyn_cast_if_present<Value>(foldResults[i])) {
276 results.emplace_back(repl);
282 Attribute attrRepl = cast<Attribute>(foldResults[i]);
284 tryGetOrCreateConstant(uniquedConstants, dialect, attrRepl,
285 res.
getType(), erasedFoldedLocation)) {
290 if (opBlock == constOp->getBlock() && &opBlock->
front() != constOp)
291 rewriter.moveOpBefore(constOp, &opBlock->
front());
293 results.push_back(constOp->getResult(0));
298 for (Operation &op : llvm::make_early_inc_range(
299 llvm::make_range(entry.begin(), rewriter.getInsertionPoint()))) {
301 rewriter.eraseOp(&op);
314OperationFolder::tryGetOrCreateConstant(ConstantMap &uniquedConstants,
318 auto constKey = std::make_tuple(dialect, value, type);
319 Operation *&constOp = uniquedConstants[constKey];
321 if (loc != constOp->
getLoc())
322 constOp->
setLoc(erasedFoldedLocation);
332 if (newDialect == dialect) {
333 referencedDialects[constOp].push_back(dialect);
339 auto newKey = std::make_tuple(newDialect, value, type);
343 if (
auto *existingOp = uniquedConstants.lookup(newKey)) {
345 rewriter.eraseOp(constOp);
346 referencedDialects[existingOp].push_back(dialect);
347 if (loc != existingOp->getLoc())
348 existingOp->setLoc(erasedFoldedLocation);
349 return constOp = existingOp;
353 referencedDialects[constOp].assign({dialect, newDialect});
354 auto newIt = uniquedConstants.insert({newKey, constOp});
355 return newIt.first->second;
static Region * getInsertionRegion(DialectInterfaceCollection< DialectFoldInterface > &interfaces, Block *insertionBlock)
Given an operation, find the parent region that folded constants should be inserted into.
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
A collection of dialect interfaces within a context, for a given concrete interface type.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
virtual Operation * materializeConstant(OpBuilder &builder, Attribute value, Type type, Location loc)
Registered hook to materialize a single constant operation from a given attribute value with the desi...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
This class helps build Operations.
Block::iterator getInsertionPoint() const
Returns the current insertion point of the builder.
Set of flags used to control the behavior of the various IR print methods (e.g.
This class provides the API for ops that are known to be isolated from above.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Value getOrCreateConstant(Block *block, Dialect *dialect, Attribute value, Type type)
Get or create a constant for use in the specified block.
void clear()
Clear out any constants cached inside of the folder.
ConstantInsertionResult
The effect of inserting a known constant on the IR.
@ Hoisted
The operation was retained but moved to the insertion point.
@ Unchanged
The operation was retained without modifying the IR.
@ Replaced
The operation was replaced with an existing constant and erased.
ConstantInsertionResult insertKnownConstant(Operation *op, Attribute constValue={})
Tries to fold a pre-existing constant operation.
LogicalResult tryToFold(Operation *op, bool *inPlaceUpdate=nullptr, int maxIterations=INT_MAX)
Tries to perform folding on the given op, including unifying deduplicated constants.
void notifyRemoval(Operation *op)
Notifies that the given constant op should be remove from this OperationFolder's internal bookkeeping...
Operation is the basic unit of execution within MLIR.
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
LogicalResult fold(ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Attempt to fold this operation with the specified constant operand values.
Block * getBlock()
Returns the operation block that contains this operation.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
result_type_iterator result_type_begin()
result_range getResults()
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.