#include "mlir/IR/Region.h"
#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
using namespace mlir;
Region::Region(Operation *container) : container(container) {}
Region::~Region() {
dropAllReferences();
}
MLIRContext *Region::getContext() {
assert(container && "region is not attached to a container");
return container->getContext();
}
Location Region::getLoc() {
assert(container && "region is not attached to a container");
return container->getLoc();
}
auto Region::getArgumentTypes() -> ValueTypeRange<BlockArgListType> {
return ValueTypeRange<BlockArgListType>(getArguments());
}
iterator_range<Region::args_iterator>
Region::addArguments(TypeRange types, ArrayRef<Location> locs) {
return front().addArguments(types, locs);
}
Region *Region::getParentRegion() {
assert(container && "region is not attached to a container");
return container->getParentRegion();
}
bool Region::isProperAncestor(Region *other) {
if (this == other)
return false;
while ((other = other->getParentRegion())) {
if (this == other)
return true;
}
return false;
}
unsigned Region::getRegionNumber() {
return this - &getParentOp()->getRegions()[0];
}
void Region::cloneInto(Region *dest, IRMapping &mapper) {
assert(dest && "expected valid region to clone into");
cloneInto(dest, dest->end(), mapper);
}
void Region::cloneInto(Region *dest, Region::iterator destPos,
IRMapping &mapper) {
assert(dest && "expected valid region to clone into");
assert(this != dest && "cannot clone region into itself");
if (empty())
return;
for (Block &block : *this) {
Block *newBlock = new Block();
mapper.map(&block, newBlock);
for (auto arg : block.getArguments())
if (!mapper.contains(arg))
mapper.map(arg, newBlock->addArgument(arg.getType(), arg.getLoc()));
dest->getBlocks().insert(destPos, newBlock);
}
auto newBlocksRange =
llvm::make_range(Region::iterator(mapper.lookup(&front())), destPos);
auto cloneOptions =
Operation::CloneOptions::all().cloneRegions(false).cloneOperands(false);
for (auto zippedBlocks : llvm::zip(*this, newBlocksRange)) {
Block &sourceBlock = std::get<0>(zippedBlocks);
Block &clonedBlock = std::get<1>(zippedBlocks);
for (Operation &op : sourceBlock)
clonedBlock.push_back(op.clone(mapper, cloneOptions));
}
SmallVector<Value> operands;
for (auto zippedBlocks : llvm::zip(*this, newBlocksRange)) {
for (auto ops :
llvm::zip(std::get<0>(zippedBlocks), std::get<1>(zippedBlocks))) {
Operation &source = std::get<0>(ops);
Operation &clone = std::get<1>(ops);
operands.resize(source.getNumOperands());
llvm::transform(
source.getOperands(), operands.begin(),
[&](Value operand) { return mapper.lookupOrDefault(operand); });
clone.setOperands(operands);
for (auto regions : llvm::zip(source.getRegions(), clone.getRegions()))
std::get<0>(regions).cloneInto(&std::get<1>(regions), mapper);
}
}
}
Block *Region::findAncestorBlockInRegion(Block &block) {
Block *currBlock = █
while (currBlock->getParent() != this) {
Operation *parentOp = currBlock->getParentOp();
if (!parentOp || !parentOp->getBlock())
return nullptr;
currBlock = parentOp->getBlock();
}
return currBlock;
}
Operation *Region::findAncestorOpInRegion(Operation &op) {
Operation *curOp = &op;
while (Region *opRegion = curOp->getParentRegion()) {
if (opRegion == this)
return curOp;
curOp = opRegion->getParentOp();
if (!curOp)
return nullptr;
}
return nullptr;
}
void Region::dropAllReferences() {
for (Block &b : *this)
b.dropAllReferences();
}
Region *llvm::ilist_traits<::mlir::Block>::getParentRegion() {
size_t offset(
size_t(&((Region *)nullptr->*Region::getSublistAccess(nullptr))));
iplist<Block> *anchor(static_cast<iplist<Block> *>(this));
return reinterpret_cast<Region *>(reinterpret_cast<char *>(anchor) - offset);
}
void llvm::ilist_traits<::mlir::Block>::addNodeToList(Block *block) {
assert(!block->getParent() && "already in a region!");
block->parentValidOpOrderPair.setPointer(getParentRegion());
}
void llvm::ilist_traits<::mlir::Block>::removeNodeFromList(Block *block) {
assert(block->getParent() && "not already in a region!");
block->parentValidOpOrderPair.setPointer(nullptr);
}
void llvm::ilist_traits<::mlir::Block>::transferNodesFromList(
ilist_traits<Block> &otherList, block_iterator first, block_iterator last) {
auto *curParent = getParentRegion();
if (curParent == otherList.getParentRegion())
return;
for (; first != last; ++first)
first->parentValidOpOrderPair.setPointer(curParent);
}
Region::OpIterator::OpIterator(Region *region, bool end)
: region(region), block(end ? region->end() : region->begin()) {
if (!region->empty())
skipOverBlocksWithNoOps();
}
Region::OpIterator &Region::OpIterator::operator++() {
if (operation != block->end())
++operation;
if (operation == block->end()) {
++block;
skipOverBlocksWithNoOps();
}
return *this;
}
void Region::OpIterator::skipOverBlocksWithNoOps() {
while (block != region->end() && block->empty())
++block;
if (block == region->end())
operation = {};
else
operation = block->begin();
}
RegionRange::RegionRange(MutableArrayRef<Region> regions)
: RegionRange(regions.data(), regions.size()) {}
RegionRange::RegionRange(ArrayRef<std::unique_ptr<Region>> regions)
: RegionRange(regions.data(), regions.size()) {}
RegionRange::RegionRange(ArrayRef<Region *> regions)
: RegionRange(const_cast<Region **>(regions.data()), regions.size()) {}
RegionRange::OwnerT RegionRange::offset_base(const OwnerT &owner,
ptrdiff_t index) {
if (auto *region = llvm::dyn_cast_if_present<const std::unique_ptr<Region> *>(owner))
return region + index;
if (auto **region = llvm::dyn_cast_if_present<Region **>(owner))
return region + index;
return &owner.get<Region *>()[index];
}
Region *RegionRange::dereference_iterator(const OwnerT &owner,
ptrdiff_t index) {
if (auto *region = llvm::dyn_cast_if_present<const std::unique_ptr<Region> *>(owner))
return region[index].get();
if (auto **region = llvm::dyn_cast_if_present<Region **>(owner))
return region[index];
return &owner.get<Region *>()[index];
}