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 ®ion, 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 ®ion, 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 ®ion, 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 ®ion, 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 ®ion, Block *before) {
36249b29dd1SRiver Riddle cloneRegionBefore(region, *before->getParent(), before->getIterator());
36349b29dd1SRiver Riddle }
364