19 #include "llvm/Support/DebugLog.h"
27 Block *insertionBlock) {
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())) {
84 op->
setLoc(erasedFoldedLocation);
95 if (results.empty()) {
97 *inPlaceUpdate =
true;
98 if (
auto *rewriteListener = dyn_cast_if_present<RewriterBase::Listener>(
101 rewriteListener->notifyOperationModified(op);
118 if (isFolderOwnedConstant(op)) {
119 if (&opBlock->
front() != op && !isFolderOwnedConstant(op->getPrevNode())) {
121 op->
setLoc(erasedFoldedLocation);
129 assert(constValue &&
"expected `op` to be a constant");
136 expectedValue == constValue &&
137 "provided constant value was not the expected value of the constant");
143 auto &uniquedConstants = foldScopes[insertRegion];
144 Operation *&folderConstOp = uniquedConstants[std::make_tuple(
151 folderConstOp->
setLoc(erasedFoldedLocation);
161 if (opBlock != insertBlock) {
163 op->
setLoc(erasedFoldedLocation);
164 }
else if (&insertBlock->
front() != op &&
165 !isFolderOwnedConstant(op->getPrevNode())) {
170 referencedDialects[op].push_back(op->
getDialect());
178 auto it = referencedDialects.find(op);
179 if (it == referencedDialects.end())
189 auto &uniquedConstants =
194 for (
auto *dialect : it->second)
195 uniquedConstants.erase(std::make_tuple(dialect, constValue, type));
196 referencedDialects.erase(it);
202 referencedDialects.clear();
211 auto &entry = insertRegion->front();
216 auto &uniquedConstants = foldScopes[insertRegion];
217 Operation *constOp = tryGetOrCreateConstant(uniquedConstants, dialect, value,
218 type, erasedFoldedLocation);
222 bool OperationFolder::isFolderOwnedConstant(
Operation *op)
const {
223 return referencedDialects.count(op);
236 LDBG() <<
"Folded in place #" << count
238 }
while (count++ < maxIterations && foldResults.empty() &&
239 succeeded(op->
fold(foldResults)));
241 if (
failed(processFoldResults(op, results, foldResults)))
247 OperationFolder::processFoldResults(
Operation *op,
251 if (foldResults.empty())
258 auto &entry = insertRegion->front();
262 auto &uniquedConstants = foldScopes[insertRegion];
267 assert(!foldResults[i].isNull() &&
"expected valid OpFoldResult");
270 if (
auto repl = llvm::dyn_cast_if_present<Value>(foldResults[i])) {
271 results.emplace_back(repl);
277 Attribute attrRepl = cast<Attribute>(foldResults[i]);
279 tryGetOrCreateConstant(uniquedConstants, dialect, attrRepl,
280 res.getType(), erasedFoldedLocation)) {
285 if (opBlock == constOp->getBlock() && &opBlock->
front() != constOp)
288 results.push_back(constOp->getResult(0));
293 for (
Operation &op : llvm::make_early_inc_range(
309 OperationFolder::tryGetOrCreateConstant(ConstantMap &uniquedConstants,
313 auto constKey = std::make_tuple(dialect, value, type);
314 Operation *&constOp = uniquedConstants[constKey];
316 if (loc != constOp->
getLoc())
317 constOp->
setLoc(erasedFoldedLocation);
327 if (newDialect == dialect) {
328 referencedDialects[constOp].push_back(dialect);
334 auto newKey = std::make_tuple(newDialect, value, type);
338 if (
auto *existingOp = uniquedConstants.lookup(newKey)) {
341 referencedDialects[existingOp].push_back(dialect);
342 if (loc != existingOp->getLoc())
343 existingOp->setLoc(erasedFoldedLocation);
344 return constOp = existingOp;
348 referencedDialects[constOp].assign({dialect, newDialect});
349 auto newIt = uniquedConstants.insert({newKey, constOp});
350 return newIt.first->second;
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.
static Region * getInsertionRegion(DialectInterfaceCollection< DialectFoldInterface > &interfaces, Block *insertionBlock)
Given an operation, find the parent region that folded constants should be inserted into.
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.
void moveBefore(Block *block)
Unlink this block from its current region and insert it right before the specific block.
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.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
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.
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...
bool insertKnownConstant(Operation *op, Attribute constValue={})
Tries to fold a pre-existing constant operation.
Operation is the basic unit of execution within MLIR.
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
LogicalResult fold(ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Attempt to fold this operation with the specified constant operand values.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
Block * getBlock()
Returns the operation block that contains this operation.
result_type_iterator result_type_begin()
void moveBefore(Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
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.
Operation * getParentOp()
Return the parent operation this region is attached to.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
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.