MLIR  14.0.0git
Region.cpp
Go to the documentation of this file.
1 //===- Region.cpp - MLIR Region Class -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "mlir/IR/Region.h"
11 #include "mlir/IR/Operation.h"
12 using namespace mlir;
13 
14 Region::Region(Operation *container) : container(container) {}
15 
17  // Operations may have cyclic references, which need to be dropped before we
18  // can start deleting them.
20 }
21 
22 /// Return the context this region is inserted in. The region must have a valid
23 /// parent container.
25  assert(container && "region is not attached to a container");
26  return container->getContext();
27 }
28 
29 /// Return a location for this region. This is the location attached to the
30 /// parent container. The region must have a valid parent container.
32  assert(container && "region is not attached to a container");
33  return container->getLoc();
34 }
35 
38 }
39 
42  return front().addArguments(types, locs);
43 }
44 
46  assert(container && "region is not attached to a container");
47  return container->getParentRegion();
48 }
49 
51  if (this == other)
52  return false;
53 
54  while ((other = other->getParentRegion())) {
55  if (this == other)
56  return true;
57  }
58  return false;
59 }
60 
61 /// Return the number of this region in the parent operation.
63  // Regions are always stored consecutively, so use pointer subtraction to
64  // figure out what number this is.
65  return this - &getParentOp()->getRegions()[0];
66 }
67 
68 /// Clone the internal blocks from this region into `dest`. Any
69 /// cloned blocks are appended to the back of dest.
71  assert(dest && "expected valid region to clone into");
72  cloneInto(dest, dest->end(), mapper);
73 }
74 
75 /// Clone this region into 'dest' before the given position in 'dest'.
77  BlockAndValueMapping &mapper) {
78  assert(dest && "expected valid region to clone into");
79  assert(this != dest && "cannot clone region into itself");
80 
81  // If the list is empty there is nothing to clone.
82  if (empty())
83  return;
84 
85  for (Block &block : *this) {
86  Block *newBlock = new Block();
87  mapper.map(&block, newBlock);
88 
89  // Clone the block arguments. The user might be deleting arguments to the
90  // block by specifying them in the mapper. If so, we don't add the
91  // argument to the cloned block.
92  for (auto arg : block.getArguments())
93  if (!mapper.contains(arg))
94  mapper.map(arg, newBlock->addArgument(arg.getType(), arg.getLoc()));
95 
96  // Clone and remap the operations within this block.
97  for (auto &op : block)
98  newBlock->push_back(op.clone(mapper));
99 
100  dest->getBlocks().insert(destPos, newBlock);
101  }
102 
103  // Now that each of the blocks have been cloned, go through and remap the
104  // operands of each of the operations.
105  auto remapOperands = [&](Operation *op) {
106  for (auto &operand : op->getOpOperands())
107  if (auto mappedOp = mapper.lookupOrNull(operand.get()))
108  operand.set(mappedOp);
109  for (auto &succOp : op->getBlockOperands())
110  if (auto *mappedOp = mapper.lookupOrNull(succOp.get()))
111  succOp.set(mappedOp);
112  };
113 
114  for (iterator it(mapper.lookup(&front())); it != destPos; ++it)
115  it->walk(remapOperands);
116 }
117 
118 /// Returns 'block' if 'block' lies in this region, or otherwise finds the
119 /// ancestor of 'block' that lies in this region. Returns nullptr if the latter
120 /// fails.
122  Block *currBlock = █
123  while (currBlock->getParent() != this) {
124  Operation *parentOp = currBlock->getParentOp();
125  if (!parentOp || !parentOp->getBlock())
126  return nullptr;
127  currBlock = parentOp->getBlock();
128  }
129  return currBlock;
130 }
131 
132 /// Returns 'op' if 'op' lies in this region, or otherwise finds the
133 /// ancestor of 'op' that lies in this region. Returns nullptr if the
134 /// latter fails.
136  Operation *curOp = &op;
137  while (Region *opRegion = curOp->getParentRegion()) {
138  if (opRegion == this)
139  return curOp;
140 
141  curOp = opRegion->getParentOp();
142  if (!curOp)
143  return nullptr;
144  }
145  return nullptr;
146 }
147 
149  for (Block &b : *this)
150  b.dropAllReferences();
151 }
152 
153 Region *llvm::ilist_traits<::mlir::Block>::getParentRegion() {
154  size_t offset(
155  size_t(&((Region *)nullptr->*Region::getSublistAccess(nullptr))));
156  iplist<Block> *anchor(static_cast<iplist<Block> *>(this));
157  return reinterpret_cast<Region *>(reinterpret_cast<char *>(anchor) - offset);
158 }
159 
160 /// This is a trait method invoked when a basic block is added to a region.
161 /// We keep the region pointer up to date.
163  assert(!block->getParent() && "already in a region!");
164  block->parentValidOpOrderPair.setPointer(getParentRegion());
165 }
166 
167 /// This is a trait method invoked when an operation is removed from a
168 /// region. We keep the region pointer up to date.
170  assert(block->getParent() && "not already in a region!");
171  block->parentValidOpOrderPair.setPointer(nullptr);
172 }
173 
174 /// This is a trait method invoked when an operation is moved from one block
175 /// to another. We keep the block pointer up to date.
177  ilist_traits<Block> &otherList, block_iterator first, block_iterator last) {
178  // If we are transferring operations within the same function, the parent
179  // pointer doesn't need to be updated.
180  auto *curParent = getParentRegion();
181  if (curParent == otherList.getParentRegion())
182  return;
183 
184  // Update the 'parent' member of each Block.
185  for (; first != last; ++first)
186  first->parentValidOpOrderPair.setPointer(curParent);
187 }
188 
189 //===----------------------------------------------------------------------===//
190 // Region::OpIterator
191 //===----------------------------------------------------------------------===//
192 
194  : region(region), block(end ? region->end() : region->begin()) {
195  if (!region->empty())
196  skipOverBlocksWithNoOps();
197 }
198 
200  // We increment over operations, if we reach the last use then move to next
201  // block.
202  if (operation != block->end())
203  ++operation;
204  if (operation == block->end()) {
205  ++block;
206  skipOverBlocksWithNoOps();
207  }
208  return *this;
209 }
210 
211 void Region::OpIterator::skipOverBlocksWithNoOps() {
212  while (block != region->end() && block->empty())
213  ++block;
214 
215  // If we are at the last block, then set the operation to first operation of
216  // next block (sentinel value used for end).
217  if (block == region->end())
218  operation = {};
219  else
220  operation = block->begin();
221 }
222 
223 //===----------------------------------------------------------------------===//
224 // RegionRange
225 //===----------------------------------------------------------------------===//
226 
228  : RegionRange(regions.data(), regions.size()) {}
229 RegionRange::RegionRange(ArrayRef<std::unique_ptr<Region>> regions)
230  : RegionRange(regions.data(), regions.size()) {}
231 
232 /// See `llvm::detail::indexed_accessor_range_base` for details.
233 RegionRange::OwnerT RegionRange::offset_base(const OwnerT &owner,
234  ptrdiff_t index) {
235  if (auto *operand = owner.dyn_cast<const std::unique_ptr<Region> *>())
236  return operand + index;
237  return &owner.get<Region *>()[index];
238 }
239 /// See `llvm::detail::indexed_accessor_range_base` for details.
240 Region *RegionRange::dereference_iterator(const OwnerT &owner,
241  ptrdiff_t index) {
242  if (auto *operand = owner.dyn_cast<const std::unique_ptr<Region> *>())
243  return operand[index].get();
244  return &owner.get<Region *>()[index];
245 }
Include the generated interface declarations.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:423
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
Definition: Block.cpp:30
BlockListType & getBlocks()
Definition: Region.h:45
Block represents an ordered list of Operations.
Definition: Block.h:29
Block & front()
Definition: Region.h:65
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
Definition: Block.cpp:148
BlockListType::iterator iterator
Definition: Region.h:52
T lookup(T from) const
Lookup a mapped value within the map.
This class provides iteration over the held operations of blocks directly within a region...
Definition: Region.h:132
BlockArgListType getArguments()
Definition: Region.h:81
Block * getBlock()
Returns the operation block that contains this operation.
Definition: Operation.h:96
void addNodeToList(Block *block)
This is a trait method invoked when a basic block is added to a region.
Definition: Region.cpp:162
Region * getParent() const
Provide a &#39;getParent&#39; method for ilist_node_with_parent methods.
Definition: Block.cpp:26
void dropAllReferences()
Drop all operand uses from operations within this region, which is an essential step in breaking cycl...
Definition: Region.cpp:148
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
void map(Block *from, Block *to)
Inserts a new mapping for &#39;from&#39; to &#39;to&#39;.
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:99
Region * getParentRegion()
Return the region containing this region or nullptr if the region is attached to a top-level operatio...
Definition: Region.cpp:45
bool empty()
Definition: Region.h:60
unsigned getRegionNumber()
Return the number of this region in the parent operation.
Definition: Region.cpp:62
iterator begin()
Definition: Region.h:55
Block * lookupOrNull(Block *from) const
Lookup a mapped value within the map.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:117
RegionRange(MutableArrayRef< Region > regions=llvm::None)
Definition: Region.cpp:227
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:106
void transferNodesFromList(ilist_traits< Block > &otherList, block_iterator first, block_iterator last)
This is a trait method invoked when an operation is moved from one block to another.
Definition: Region.cpp:176
BlockArgListType getArguments()
Definition: Block.h:76
OpIterator(Region *region, bool end=false)
Initialize OpIterator for a region, specify end to return the iterator to last operation.
Definition: Region.cpp:193
void cloneInto(Region *dest, BlockAndValueMapping &mapper)
Clone the internal blocks from this region into dest.
Definition: Region.cpp:70
Operation * findAncestorOpInRegion(Operation &op)
Returns &#39;op&#39; if &#39;op&#39; lies in this region, or otherwise finds the ancestor of &#39;op&#39; that lies in this r...
Definition: Region.cpp:135
Region()=default
Operation * getParentOp()
Return the parent operation this region is attached to.
Definition: Region.h:200
iterator_range< args_iterator > addArguments(TypeRange types, ArrayRef< Location > locs)
Add one argument to the argument list for each type specified in the list.
Definition: Region.cpp:41
simple_ilist<::mlir::Block >::iterator block_iterator
Definition: BlockSupport.h:249
This class implements iteration on the types of a given range of values.
Definition: Block.h:26
OpIterator & operator++()
Definition: Region.cpp:199
Block * findAncestorBlockInRegion(Block &block)
Returns &#39;block&#39; if &#39;block&#39; lies in this region, or otherwise finds the ancestor of &#39;block&#39; that lies ...
Definition: Region.cpp:121
void dropAllReferences()
This drops all operand uses from operations within this block, which is an essential step in breaking...
Definition: Block.cpp:77
MLIRContext * getContext()
Return the context this region is inserted in.
Definition: Region.cpp:24
bool contains(Block *from) const
Checks to see if a mapping for &#39;from&#39; exists.
void push_back(Operation *op)
Definition: Block.h:140
iterator end()
Definition: Region.h:56
bool isProperAncestor(Region *other)
Return true if this region is a proper ancestor of the other region.
Definition: Region.cpp:50
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
void removeNodeFromList(Block *block)
This is a trait method invoked when an operation is removed from a region.
Definition: Region.cpp:169
This class provides an abstraction over the different types of ranges over Regions.
Definition: Region.h:322
static BlockListType Region::* getSublistAccess(Block *)
getSublistAccess() - Returns pointer to member of region.
Definition: Region.h:71
ValueTypeRange< BlockArgListType > getArgumentTypes()
Returns the argument types of the first block within the region.
Definition: Region.cpp:36
Region * getParentRegion()
Returns the region to which the instruction belongs.
Definition: Operation.h:113
Location getLoc()
Return a location for this region.
Definition: Region.cpp:31
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Definition: Block.cpp:141