17de0da95SChris Lattner //===- PatternMatch.cpp - Base classes for pattern match ------------------===//
27de0da95SChris Lattner //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67de0da95SChris Lattner //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
87de0da95SChris Lattner 
97de0da95SChris Lattner #include "mlir/IR/PatternMatch.h"
1049b29dd1SRiver Riddle #include "mlir/IR/BlockAndValueMapping.h"
116fb3d597SDiego Caballero 
127de0da95SChris Lattner using namespace mlir;
137de0da95SChris Lattner 
14b99bd771SRiver Riddle //===----------------------------------------------------------------------===//
15b99bd771SRiver Riddle // PatternBenefit
16b99bd771SRiver Riddle //===----------------------------------------------------------------------===//
17b99bd771SRiver Riddle 
PatternBenefit(unsigned benefit)187de0da95SChris Lattner PatternBenefit::PatternBenefit(unsigned benefit) : representation(benefit) {
197de0da95SChris Lattner   assert(representation == benefit && benefit != ImpossibleToMatchSentinel &&
207de0da95SChris Lattner          "This pattern match benefit is too large to represent");
217de0da95SChris Lattner }
227de0da95SChris Lattner 
getBenefit() const237de0da95SChris Lattner unsigned short PatternBenefit::getBenefit() const {
243e98fbf4SRiver Riddle   assert(!isImpossibleToMatch() && "Pattern doesn't match");
257de0da95SChris Lattner   return representation;
267de0da95SChris Lattner }
277de0da95SChris Lattner 
287de0da95SChris Lattner //===----------------------------------------------------------------------===//
29b99bd771SRiver Riddle // Pattern
307de0da95SChris Lattner //===----------------------------------------------------------------------===//
317de0da95SChris Lattner 
3276f3c2f3SRiver Riddle //===----------------------------------------------------------------------===//
3376f3c2f3SRiver Riddle // OperationName Root Constructors
3476f3c2f3SRiver Riddle 
Pattern(StringRef rootName,PatternBenefit benefit,MLIRContext * context,ArrayRef<StringRef> generatedNames)3586a5323fSChris Lattner Pattern::Pattern(StringRef rootName, PatternBenefit benefit,
3676f3c2f3SRiver Riddle                  MLIRContext *context, ArrayRef<StringRef> generatedNames)
3776f3c2f3SRiver Riddle     : Pattern(OperationName(rootName, context).getAsOpaquePointer(),
3876f3c2f3SRiver Riddle               RootKind::OperationName, generatedNames, benefit, context) {}
3976f3c2f3SRiver Riddle 
4076f3c2f3SRiver Riddle //===----------------------------------------------------------------------===//
4176f3c2f3SRiver Riddle // MatchAnyOpTypeTag Root Constructors
4276f3c2f3SRiver Riddle 
Pattern(MatchAnyOpTypeTag tag,PatternBenefit benefit,MLIRContext * context,ArrayRef<StringRef> generatedNames)4376f3c2f3SRiver Riddle Pattern::Pattern(MatchAnyOpTypeTag tag, PatternBenefit benefit,
4476f3c2f3SRiver Riddle                  MLIRContext *context, ArrayRef<StringRef> generatedNames)
4576f3c2f3SRiver Riddle     : Pattern(nullptr, RootKind::Any, generatedNames, benefit, context) {}
4676f3c2f3SRiver Riddle 
4776f3c2f3SRiver Riddle //===----------------------------------------------------------------------===//
4876f3c2f3SRiver Riddle // MatchInterfaceOpTypeTag Root Constructors
4976f3c2f3SRiver Riddle 
Pattern(MatchInterfaceOpTypeTag tag,TypeID interfaceID,PatternBenefit benefit,MLIRContext * context,ArrayRef<StringRef> generatedNames)5076f3c2f3SRiver Riddle Pattern::Pattern(MatchInterfaceOpTypeTag tag, TypeID interfaceID,
5176f3c2f3SRiver Riddle                  PatternBenefit benefit, MLIRContext *context,
5276f3c2f3SRiver Riddle                  ArrayRef<StringRef> generatedNames)
5376f3c2f3SRiver Riddle     : Pattern(interfaceID.getAsOpaquePointer(), RootKind::InterfaceID,
5476f3c2f3SRiver Riddle               generatedNames, benefit, context) {}
5576f3c2f3SRiver Riddle 
5676f3c2f3SRiver Riddle //===----------------------------------------------------------------------===//
5776f3c2f3SRiver Riddle // MatchTraitOpTypeTag Root Constructors
5876f3c2f3SRiver Riddle 
Pattern(MatchTraitOpTypeTag tag,TypeID traitID,PatternBenefit benefit,MLIRContext * context,ArrayRef<StringRef> generatedNames)5976f3c2f3SRiver Riddle Pattern::Pattern(MatchTraitOpTypeTag tag, TypeID traitID,
6076f3c2f3SRiver Riddle                  PatternBenefit benefit, MLIRContext *context,
6176f3c2f3SRiver Riddle                  ArrayRef<StringRef> generatedNames)
6276f3c2f3SRiver Riddle     : Pattern(traitID.getAsOpaquePointer(), RootKind::TraitID, generatedNames,
6376f3c2f3SRiver Riddle               benefit, context) {}
6476f3c2f3SRiver Riddle 
6576f3c2f3SRiver Riddle //===----------------------------------------------------------------------===//
6676f3c2f3SRiver Riddle // General Constructors
6776f3c2f3SRiver Riddle 
Pattern(const void * rootValue,RootKind rootKind,ArrayRef<StringRef> generatedNames,PatternBenefit benefit,MLIRContext * context)6876f3c2f3SRiver Riddle Pattern::Pattern(const void *rootValue, RootKind rootKind,
6976f3c2f3SRiver Riddle                  ArrayRef<StringRef> generatedNames, PatternBenefit benefit,
7086a5323fSChris Lattner                  MLIRContext *context)
7176f3c2f3SRiver Riddle     : rootValue(rootValue), rootKind(rootKind), benefit(benefit),
7276f3c2f3SRiver Riddle       contextAndHasBoundedRecursion(context, false) {
7376f3c2f3SRiver Riddle   if (generatedNames.empty())
7476f3c2f3SRiver Riddle     return;
75b99bd771SRiver Riddle   generatedOps.reserve(generatedNames.size());
76b99bd771SRiver Riddle   std::transform(generatedNames.begin(), generatedNames.end(),
77b99bd771SRiver Riddle                  std::back_inserter(generatedOps), [context](StringRef name) {
78b99bd771SRiver Riddle                    return OperationName(name, context);
79b99bd771SRiver Riddle                  });
80b99bd771SRiver Riddle }
813f2530cdSChris Lattner 
823f2530cdSChris Lattner //===----------------------------------------------------------------------===//
83b99bd771SRiver Riddle // RewritePattern
843f2530cdSChris Lattner //===----------------------------------------------------------------------===//
853f2530cdSChris Lattner 
rewrite(Operation * op,PatternRewriter & rewriter) const86f9d91531SRiver Riddle void RewritePattern::rewrite(Operation *op, PatternRewriter &rewriter) const {
875de726f4SRiver Riddle   llvm_unreachable("need to implement either matchAndRewrite or one of the "
885de726f4SRiver Riddle                    "rewrite functions!");
895de726f4SRiver Riddle }
905de726f4SRiver Riddle 
match(Operation * op) const913145427dSRiver Riddle LogicalResult RewritePattern::match(Operation *op) const {
925de726f4SRiver Riddle   llvm_unreachable("need to implement either match or matchAndRewrite!");
937de0da95SChris Lattner }
947de0da95SChris Lattner 
95b99bd771SRiver Riddle /// Out-of-line vtable anchor.
anchor()96b99bd771SRiver Riddle void RewritePattern::anchor() {}
97b99bd771SRiver Riddle 
98b99bd771SRiver Riddle //===----------------------------------------------------------------------===//
99abfd1a8bSRiver Riddle // PDLValue
100abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
101abfd1a8bSRiver Riddle 
print(raw_ostream & os) const10285ab413bSRiver Riddle void PDLValue::print(raw_ostream &os) const {
10385ab413bSRiver Riddle   if (!value) {
10485ab413bSRiver Riddle     os << "<NULL-PDLValue>";
105abfd1a8bSRiver Riddle     return;
106abfd1a8bSRiver Riddle   }
10785ab413bSRiver Riddle   switch (kind) {
10885ab413bSRiver Riddle   case Kind::Attribute:
10985ab413bSRiver Riddle     os << cast<Attribute>();
11085ab413bSRiver Riddle     break;
11185ab413bSRiver Riddle   case Kind::Operation:
11285ab413bSRiver Riddle     os << *cast<Operation *>();
11385ab413bSRiver Riddle     break;
11485ab413bSRiver Riddle   case Kind::Type:
11585ab413bSRiver Riddle     os << cast<Type>();
11685ab413bSRiver Riddle     break;
11785ab413bSRiver Riddle   case Kind::TypeRange:
11885ab413bSRiver Riddle     llvm::interleaveComma(cast<TypeRange>(), os);
11985ab413bSRiver Riddle     break;
12085ab413bSRiver Riddle   case Kind::Value:
12185ab413bSRiver Riddle     os << cast<Value>();
12285ab413bSRiver Riddle     break;
12385ab413bSRiver Riddle   case Kind::ValueRange:
12485ab413bSRiver Riddle     llvm::interleaveComma(cast<ValueRange>(), os);
12585ab413bSRiver Riddle     break;
126abfd1a8bSRiver Riddle   }
127abfd1a8bSRiver Riddle }
128abfd1a8bSRiver Riddle 
print(raw_ostream & os,Kind kind)1293eb1647aSStanislav Funiak void PDLValue::print(raw_ostream &os, Kind kind) {
1303eb1647aSStanislav Funiak   switch (kind) {
1313eb1647aSStanislav Funiak   case Kind::Attribute:
1323eb1647aSStanislav Funiak     os << "Attribute";
1333eb1647aSStanislav Funiak     break;
1343eb1647aSStanislav Funiak   case Kind::Operation:
1353eb1647aSStanislav Funiak     os << "Operation";
1363eb1647aSStanislav Funiak     break;
1373eb1647aSStanislav Funiak   case Kind::Type:
1383eb1647aSStanislav Funiak     os << "Type";
1393eb1647aSStanislav Funiak     break;
1403eb1647aSStanislav Funiak   case Kind::TypeRange:
1413eb1647aSStanislav Funiak     os << "TypeRange";
1423eb1647aSStanislav Funiak     break;
1433eb1647aSStanislav Funiak   case Kind::Value:
1443eb1647aSStanislav Funiak     os << "Value";
1453eb1647aSStanislav Funiak     break;
1463eb1647aSStanislav Funiak   case Kind::ValueRange:
1473eb1647aSStanislav Funiak     os << "ValueRange";
1483eb1647aSStanislav Funiak     break;
1493eb1647aSStanislav Funiak   }
1503eb1647aSStanislav Funiak }
1513eb1647aSStanislav Funiak 
152abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
153abfd1a8bSRiver Riddle // PDLPatternModule
154abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
155abfd1a8bSRiver Riddle 
mergeIn(PDLPatternModule && other)156abfd1a8bSRiver Riddle void PDLPatternModule::mergeIn(PDLPatternModule &&other) {
157abfd1a8bSRiver Riddle   // Ignore the other module if it has no patterns.
158abfd1a8bSRiver Riddle   if (!other.pdlModule)
159abfd1a8bSRiver Riddle     return;
160*06c3b9c7SRiver Riddle 
161*06c3b9c7SRiver Riddle   // Steal the functions of the other module.
162*06c3b9c7SRiver Riddle   for (auto &it : other.constraintFunctions)
163*06c3b9c7SRiver Riddle     registerConstraintFunction(it.first(), std::move(it.second));
164*06c3b9c7SRiver Riddle   for (auto &it : other.rewriteFunctions)
165*06c3b9c7SRiver Riddle     registerRewriteFunction(it.first(), std::move(it.second));
166*06c3b9c7SRiver Riddle 
167abfd1a8bSRiver Riddle   // Steal the other state if we have no patterns.
168abfd1a8bSRiver Riddle   if (!pdlModule) {
169abfd1a8bSRiver Riddle     pdlModule = std::move(other.pdlModule);
170abfd1a8bSRiver Riddle     return;
171abfd1a8bSRiver Riddle   }
172abfd1a8bSRiver Riddle 
173abfd1a8bSRiver Riddle   // Merge the pattern operations from the other module into this one.
174abfd1a8bSRiver Riddle   Block *block = pdlModule->getBody();
175abfd1a8bSRiver Riddle   block->getOperations().splice(block->end(),
176abfd1a8bSRiver Riddle                                 other.pdlModule->getBody()->getOperations());
177abfd1a8bSRiver Riddle }
178abfd1a8bSRiver Riddle 
179abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
180abfd1a8bSRiver Riddle // Function Registry
181abfd1a8bSRiver Riddle 
registerConstraintFunction(StringRef name,PDLConstraintFunction constraintFn)182abfd1a8bSRiver Riddle void PDLPatternModule::registerConstraintFunction(
183abfd1a8bSRiver Riddle     StringRef name, PDLConstraintFunction constraintFn) {
184*06c3b9c7SRiver Riddle   // TODO: Is it possible to diagnose when `name` is already registered to
185*06c3b9c7SRiver Riddle   // a function that is not equivalent to `constraintFn`?
186*06c3b9c7SRiver Riddle   // Allow existing mappings in the case multiple patterns depend on the same
187*06c3b9c7SRiver Riddle   // constraint.
188*06c3b9c7SRiver Riddle   constraintFunctions.try_emplace(name, std::move(constraintFn));
189abfd1a8bSRiver Riddle }
19002c4c0d5SRiver Riddle 
registerRewriteFunction(StringRef name,PDLRewriteFunction rewriteFn)191abfd1a8bSRiver Riddle void PDLPatternModule::registerRewriteFunction(StringRef name,
192abfd1a8bSRiver Riddle                                                PDLRewriteFunction rewriteFn) {
193*06c3b9c7SRiver Riddle   // TODO: Is it possible to diagnose when `name` is already registered to
194*06c3b9c7SRiver Riddle   // a function that is not equivalent to `rewriteFn`?
195*06c3b9c7SRiver Riddle   // Allow existing mappings in the case multiple patterns depend on the same
196*06c3b9c7SRiver Riddle   // rewrite.
197*06c3b9c7SRiver Riddle   rewriteFunctions.try_emplace(name, std::move(rewriteFn));
198abfd1a8bSRiver Riddle }
199abfd1a8bSRiver Riddle 
200abfd1a8bSRiver Riddle //===----------------------------------------------------------------------===//
201ec10f066SRiver Riddle // RewriterBase
202b99bd771SRiver Riddle //===----------------------------------------------------------------------===//
203647f8cabSRiver Riddle 
~RewriterBase()204ec10f066SRiver Riddle RewriterBase::~RewriterBase() {
2057de0da95SChris Lattner   // Out of line to provide a vtable anchor for the class.
2067de0da95SChris Lattner }
2077de0da95SChris Lattner 
208c8fb6ee3SRiver Riddle /// This method replaces the uses of the results of `op` with the values in
209c8fb6ee3SRiver Riddle /// `newValues` when the provided `functor` returns true for a specific use.
210c8fb6ee3SRiver Riddle /// The number of values in `newValues` is required to match the number of
211c8fb6ee3SRiver Riddle /// results of `op`.
replaceOpWithIf(Operation * op,ValueRange newValues,bool * allUsesReplaced,llvm::unique_function<bool (OpOperand &)const> functor)212ec10f066SRiver Riddle void RewriterBase::replaceOpWithIf(
213c8fb6ee3SRiver Riddle     Operation *op, ValueRange newValues, bool *allUsesReplaced,
214c8fb6ee3SRiver Riddle     llvm::unique_function<bool(OpOperand &) const> functor) {
215c8fb6ee3SRiver Riddle   assert(op->getNumResults() == newValues.size() &&
216c8fb6ee3SRiver Riddle          "incorrect number of values to replace operation");
217c8fb6ee3SRiver Riddle 
218c8fb6ee3SRiver Riddle   // Notify the rewriter subclass that we're about to replace this root.
219c8fb6ee3SRiver Riddle   notifyRootReplaced(op);
220c8fb6ee3SRiver Riddle 
221c8fb6ee3SRiver Riddle   // Replace each use of the results when the functor is true.
222c8fb6ee3SRiver Riddle   bool replacedAllUses = true;
223c8fb6ee3SRiver Riddle   for (auto it : llvm::zip(op->getResults(), newValues)) {
224c8fb6ee3SRiver Riddle     std::get<0>(it).replaceUsesWithIf(std::get<1>(it), functor);
225c8fb6ee3SRiver Riddle     replacedAllUses &= std::get<0>(it).use_empty();
226c8fb6ee3SRiver Riddle   }
227c8fb6ee3SRiver Riddle   if (allUsesReplaced)
228c8fb6ee3SRiver Riddle     *allUsesReplaced = replacedAllUses;
229c8fb6ee3SRiver Riddle }
230c8fb6ee3SRiver Riddle 
231c8fb6ee3SRiver Riddle /// This method replaces the uses of the results of `op` with the values in
232c8fb6ee3SRiver Riddle /// `newValues` when a use is nested within the given `block`. The number of
233c8fb6ee3SRiver Riddle /// values in `newValues` is required to match the number of results of `op`.
234c8fb6ee3SRiver Riddle /// If all uses of this operation are replaced, the operation is erased.
replaceOpWithinBlock(Operation * op,ValueRange newValues,Block * block,bool * allUsesReplaced)235ec10f066SRiver Riddle void RewriterBase::replaceOpWithinBlock(Operation *op, ValueRange newValues,
236ec10f066SRiver Riddle                                         Block *block, bool *allUsesReplaced) {
237c8fb6ee3SRiver Riddle   replaceOpWithIf(op, newValues, allUsesReplaced, [block](OpOperand &use) {
238c8fb6ee3SRiver Riddle     return block->getParentOp()->isProperAncestor(use.getOwner());
239c8fb6ee3SRiver Riddle   });
240c8fb6ee3SRiver Riddle }
241c8fb6ee3SRiver Riddle 
242ec10f066SRiver Riddle /// This method replaces the results of the operation with the specified list of
243ec10f066SRiver Riddle /// values. The number of provided values must match the number of results of
244ec10f066SRiver Riddle /// the operation.
replaceOp(Operation * op,ValueRange newValues)245ec10f066SRiver Riddle void RewriterBase::replaceOp(Operation *op, ValueRange newValues) {
2461427d0f0SChris Lattner   // Notify the rewriter subclass that we're about to replace this root.
2471427d0f0SChris Lattner   notifyRootReplaced(op);
2481427d0f0SChris Lattner 
2491427d0f0SChris Lattner   assert(op->getNumResults() == newValues.size() &&
2501427d0f0SChris Lattner          "incorrect # of replacement values");
2518089f937SRiver Riddle   op->replaceAllUsesWith(newValues);
2521427d0f0SChris Lattner 
2531427d0f0SChris Lattner   notifyOperationRemoved(op);
2541427d0f0SChris Lattner   op->erase();
2551427d0f0SChris Lattner }
2561427d0f0SChris Lattner 
257dfe09cc6SRiver Riddle /// This method erases an operation that is known to have no uses. The uses of
258dfe09cc6SRiver Riddle /// the given operation *must* be known to be dead.
eraseOp(Operation * op)259ec10f066SRiver Riddle void RewriterBase::eraseOp(Operation *op) {
260dfe09cc6SRiver Riddle   assert(op->use_empty() && "expected 'op' to have no uses");
261dfe09cc6SRiver Riddle   notifyOperationRemoved(op);
262dfe09cc6SRiver Riddle   op->erase();
263dfe09cc6SRiver Riddle }
264dfe09cc6SRiver Riddle 
eraseBlock(Block * block)265ec10f066SRiver Riddle void RewriterBase::eraseBlock(Block *block) {
2663f9cdd44SUday Bondhugula   for (auto &op : llvm::make_early_inc_range(llvm::reverse(*block))) {
2673f9cdd44SUday Bondhugula     assert(op.use_empty() && "expected 'op' to have no uses");
2683f9cdd44SUday Bondhugula     eraseOp(&op);
2693f9cdd44SUday Bondhugula   }
2703f9cdd44SUday Bondhugula   block->erase();
2713f9cdd44SUday Bondhugula }
2723f9cdd44SUday Bondhugula 
2732366561aSRiver Riddle /// Merge the operations of block 'source' into the end of block 'dest'.
2742366561aSRiver Riddle /// 'source's predecessors must be empty or only contain 'dest`.
2752366561aSRiver Riddle /// 'argValues' is used to replace the block arguments of 'source' after
2762366561aSRiver Riddle /// merging.
mergeBlocks(Block * source,Block * dest,ValueRange argValues)277ec10f066SRiver Riddle void RewriterBase::mergeBlocks(Block *source, Block *dest,
2789d1a0c72SRiver Riddle                                ValueRange argValues) {
2792366561aSRiver Riddle   assert(llvm::all_of(source->getPredecessors(),
2802366561aSRiver Riddle                       [dest](Block *succ) { return succ == dest; }) &&
2812366561aSRiver Riddle          "expected 'source' to have no predecessors or only 'dest'");
2822366561aSRiver Riddle   assert(argValues.size() == source->getNumArguments() &&
2832366561aSRiver Riddle          "incorrect # of argument replacement values");
2842366561aSRiver Riddle 
2852366561aSRiver Riddle   // Replace all of the successor arguments with the provided values.
2862366561aSRiver Riddle   for (auto it : llvm::zip(source->getArguments(), argValues))
2872bdf33ccSRiver Riddle     std::get<0>(it).replaceAllUsesWith(std::get<1>(it));
2882366561aSRiver Riddle 
2892366561aSRiver Riddle   // Splice the operations of the 'source' block into the 'dest' block and erase
2902366561aSRiver Riddle   // it.
2912366561aSRiver Riddle   dest->getOperations().splice(dest->end(), source->getOperations());
2922366561aSRiver Riddle   source->dropAllUses();
2932366561aSRiver Riddle   source->erase();
2942366561aSRiver Riddle }
2952366561aSRiver Riddle 
2969c7b0c4aSRahul Joshi // Merge the operations of block 'source' before the operation 'op'. Source
2979c7b0c4aSRahul Joshi // block should not have existing predecessors or successors.
mergeBlockBefore(Block * source,Operation * op,ValueRange argValues)298ec10f066SRiver Riddle void RewriterBase::mergeBlockBefore(Block *source, Operation *op,
2999c7b0c4aSRahul Joshi                                     ValueRange argValues) {
3009c7b0c4aSRahul Joshi   assert(source->hasNoPredecessors() &&
3019c7b0c4aSRahul Joshi          "expected 'source' to have no predecessors");
3029c7b0c4aSRahul Joshi   assert(source->hasNoSuccessors() &&
3039c7b0c4aSRahul Joshi          "expected 'source' to have no successors");
3049c7b0c4aSRahul Joshi 
30541b09f4eSKazuaki Ishizaki   // Split the block containing 'op' into two, one containing all operations
3069c7b0c4aSRahul Joshi   // before 'op' (prologue) and another (epilogue) containing 'op' and all
3079c7b0c4aSRahul Joshi   // operations after it.
3089c7b0c4aSRahul Joshi   Block *prologue = op->getBlock();
3099c7b0c4aSRahul Joshi   Block *epilogue = splitBlock(prologue, op->getIterator());
3109c7b0c4aSRahul Joshi 
3119c7b0c4aSRahul Joshi   // Merge the source block at the end of the prologue.
3129c7b0c4aSRahul Joshi   mergeBlocks(source, prologue, argValues);
3139c7b0c4aSRahul Joshi 
3149c7b0c4aSRahul Joshi   // Merge the epilogue at the end the prologue.
3159c7b0c4aSRahul Joshi   mergeBlocks(epilogue, prologue);
3169c7b0c4aSRahul Joshi }
3179c7b0c4aSRahul Joshi 
3182366561aSRiver Riddle /// Split the operations starting at "before" (inclusive) out of the given
3192366561aSRiver Riddle /// block into a new block, and return it.
splitBlock(Block * block,Block::iterator before)320ec10f066SRiver Riddle Block *RewriterBase::splitBlock(Block *block, Block::iterator before) {
3212366561aSRiver Riddle   return block->splitBlock(before);
3222366561aSRiver Riddle }
3232366561aSRiver Riddle 
3246fb3d597SDiego Caballero /// 'op' and 'newOp' are known to have the same number of results, replace the
325721a30d6SChris Lattner /// uses of op with uses of newOp
replaceOpWithResultsOfAnotherOp(Operation * op,Operation * newOp)326ec10f066SRiver Riddle void RewriterBase::replaceOpWithResultsOfAnotherOp(Operation *op,
3276fb3d597SDiego Caballero                                                    Operation *newOp) {
328721a30d6SChris Lattner   assert(op->getNumResults() == newOp->getNumResults() &&
329721a30d6SChris Lattner          "replacement op doesn't match results of original op");
330721a30d6SChris Lattner   if (op->getNumResults() == 1)
3316fb3d597SDiego Caballero     return replaceOp(op, newOp->getResult(0));
3326fb3d597SDiego Caballero   return replaceOp(op, newOp->getResults());
3337de0da95SChris Lattner }
3347de0da95SChris Lattner 
3358ad35b90SAlex Zinenko /// Move the blocks that belong to "region" before the given position in
3368ad35b90SAlex Zinenko /// another region.  The two regions must be different.  The caller is in
3378ad35b90SAlex Zinenko /// charge to update create the operation transferring the control flow to the
3388ad35b90SAlex Zinenko /// region and pass it the correct block arguments.
inlineRegionBefore(Region & region,Region & parent,Region::iterator before)339ec10f066SRiver Riddle void RewriterBase::inlineRegionBefore(Region &region, Region &parent,
3408ad35b90SAlex Zinenko                                       Region::iterator before) {
3413e99d995SRiver Riddle   parent.getBlocks().splice(before, region.getBlocks());
3423e99d995SRiver Riddle }
inlineRegionBefore(Region & region,Block * before)343ec10f066SRiver Riddle void RewriterBase::inlineRegionBefore(Region &region, Block *before) {
3443e99d995SRiver Riddle   inlineRegionBefore(region, *before->getParent(), before->getIterator());
3458ad35b90SAlex Zinenko }
3468ad35b90SAlex Zinenko 
34749b29dd1SRiver Riddle /// Clone the blocks that belong to "region" before the given position in
34849b29dd1SRiver Riddle /// another region "parent". The two regions must be different. The caller is
34949b29dd1SRiver Riddle /// responsible for creating or updating the operation transferring flow of
35049b29dd1SRiver Riddle /// control to the region and passing it the correct block arguments.
cloneRegionBefore(Region & region,Region & parent,Region::iterator before,BlockAndValueMapping & mapping)351ec10f066SRiver Riddle void RewriterBase::cloneRegionBefore(Region &region, Region &parent,
35249b29dd1SRiver Riddle                                      Region::iterator before,
35349b29dd1SRiver Riddle                                      BlockAndValueMapping &mapping) {
35449b29dd1SRiver Riddle   region.cloneInto(&parent, before, mapping);
35549b29dd1SRiver Riddle }
cloneRegionBefore(Region & region,Region & parent,Region::iterator before)356ec10f066SRiver Riddle void RewriterBase::cloneRegionBefore(Region &region, Region &parent,
35749b29dd1SRiver Riddle                                      Region::iterator before) {
35849b29dd1SRiver Riddle   BlockAndValueMapping mapping;
35949b29dd1SRiver Riddle   cloneRegionBefore(region, parent, before, mapping);
36049b29dd1SRiver Riddle }
cloneRegionBefore(Region & region,Block * before)361ec10f066SRiver Riddle void RewriterBase::cloneRegionBefore(Region &region, Block *before) {
36249b29dd1SRiver Riddle   cloneRegionBefore(region, *before->getParent(), before->getIterator());
36349b29dd1SRiver Riddle }
364