forked from OSchip/llvm-project
Introduce functionality for defining region ancestor relation
Add member functions for Regions to query if another Region is a ancestor. The implementation is naive and traverses all parent regions performing one-to-one comparisons. As a side effect, this introduces `getContainingRegion` function for Operations and Values to return the Region in which they are defined, and for Regions to return the "parent" region if any. -- PiperOrigin-RevId: 245057980
This commit is contained in:
parent
9f934f2a59
commit
4beef47b35
|
@ -329,7 +329,7 @@ private:
|
|||
namespace mlir {
|
||||
|
||||
/// This class contains a list of basic blocks and has a notion of the object it
|
||||
/// is part of - a Function or an operation region.
|
||||
/// is part of - a Function or an Operation.
|
||||
class Region {
|
||||
public:
|
||||
explicit Region(Function *container = nullptr);
|
||||
|
@ -360,6 +360,10 @@ public:
|
|||
return &Region::blocks;
|
||||
}
|
||||
|
||||
/// Return the region containing this region or nullptr if it is a top-level
|
||||
/// region, i.e. a function body region.
|
||||
Region *getContainingRegion();
|
||||
|
||||
/// A Region is either a function body or a part of an operation. If it is
|
||||
/// part of an operation, then return the operation, otherwise return null.
|
||||
Operation *getContainingOp();
|
||||
|
@ -368,6 +372,15 @@ public:
|
|||
/// a Function body, then return this function, otherwise return null.
|
||||
Function *getContainingFunction();
|
||||
|
||||
/// Return true if this region is a proper ancestor of the `other` region.
|
||||
bool isProperAncestor(Region *other);
|
||||
|
||||
/// Return true if this region is ancestor of the `other` region. A region
|
||||
/// is considered as its own ancestor, use `isProperAncestor` to avoid this.
|
||||
bool isAncestor(Region *other) {
|
||||
return this == other || isProperAncestor(other);
|
||||
}
|
||||
|
||||
/// Clone the internal blocks from this region into dest. Any
|
||||
/// cloned blocks are appended to the back of dest. If the mapper
|
||||
/// contains entries for block arguments, these arguments are not included
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
Region &getBody() { return body; }
|
||||
|
||||
/// This is the list of blocks in the function.
|
||||
using RegionType = llvm::iplist<Block>;
|
||||
using RegionType = Region::RegionType;
|
||||
RegionType &getBlocks() { return body.getBlocks(); }
|
||||
|
||||
// Iteration over the block in the function.
|
||||
|
|
|
@ -717,6 +717,9 @@ public:
|
|||
/// Return the operation that this refers to.
|
||||
Operation *getOperation() { return OpState::getOperation(); }
|
||||
|
||||
/// Return the Region enclosing this Op.
|
||||
Region *getContainingRegion() { return getOperation()->getParentRegion(); }
|
||||
|
||||
/// Return true if this "op class" can match against the specified operation.
|
||||
/// This hook can be overridden with a more specific implementation in
|
||||
/// the subclass of Base.
|
||||
|
|
|
@ -113,6 +113,11 @@ public:
|
|||
/// Set the source location the operation was defined or derived from.
|
||||
void setLoc(Location loc) { location = loc; }
|
||||
|
||||
/// Returns the region to which the instruction belongs, which can be a
|
||||
/// function body region or a region that belongs to another operation.
|
||||
/// Returns nullptr if the instruction is unlinked.
|
||||
Region *getContainingRegion() const;
|
||||
|
||||
/// Returns the closest surrounding operation that contains this operation
|
||||
/// or nullptr if this is a top-level operation.
|
||||
Operation *getParentOp();
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace mlir {
|
|||
class Block;
|
||||
class Function;
|
||||
class Operation;
|
||||
class Region;
|
||||
class Value;
|
||||
|
||||
/// Operands contain a Value.
|
||||
|
@ -81,6 +82,9 @@ public:
|
|||
/// otherwise return an unknown location.
|
||||
Location getLoc();
|
||||
|
||||
/// Return the Region in which this Value is defined.
|
||||
Region *getContainingRegion();
|
||||
|
||||
using use_iterator = ValueUseIterator<OpOperand>;
|
||||
using use_range = llvm::iterator_range<use_iterator>;
|
||||
|
||||
|
|
|
@ -282,6 +282,12 @@ Region::~Region() {
|
|||
bb.dropAllReferences();
|
||||
}
|
||||
|
||||
Region *Region::getContainingRegion() {
|
||||
if (auto *inst = getContainingOp())
|
||||
return inst->getContainingRegion();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Operation *Region::getContainingOp() {
|
||||
assert(!container.isNull() && "no container");
|
||||
return container.dyn_cast<Operation *>();
|
||||
|
@ -292,6 +298,17 @@ Function *Region::getContainingFunction() {
|
|||
return container.dyn_cast<Function *>();
|
||||
}
|
||||
|
||||
bool Region::isProperAncestor(Region *other) {
|
||||
if (this == other)
|
||||
return false;
|
||||
|
||||
while ((other = other->getContainingRegion())) {
|
||||
if (this == other)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Clone the internal blocks from this region into `dest`. Any
|
||||
/// cloned blocks are appended to the back of dest.
|
||||
void Region::cloneInto(Region *dest, BlockAndValueMapping &mapper,
|
||||
|
|
|
@ -273,6 +273,10 @@ Dialect *Operation::getDialect() {
|
|||
return getContext()->getRegisteredDialect(dialectPrefix);
|
||||
}
|
||||
|
||||
Region *Operation::getContainingRegion() const {
|
||||
return block ? block->getParent() : nullptr;
|
||||
}
|
||||
|
||||
Operation *Operation::getParentOp() {
|
||||
return block ? block->getContainingOp() : nullptr;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// =============================================================================
|
||||
|
||||
#include "mlir/IR/Value.h"
|
||||
#include "mlir/IR/Block.h"
|
||||
#include "mlir/IR/Function.h"
|
||||
#include "mlir/IR/Operation.h"
|
||||
using namespace mlir;
|
||||
|
@ -45,6 +46,16 @@ Location Value::getLoc() {
|
|||
return UnknownLoc::get(getContext());
|
||||
}
|
||||
|
||||
/// Return the Region in which this Value is defined.
|
||||
Region *Value::getContainingRegion() {
|
||||
switch (getKind()) {
|
||||
case Value::Kind::BlockArgument:
|
||||
return cast<BlockArgument>(this)->getOwner()->getParent();
|
||||
case Value::Kind::OpResult:
|
||||
return getDefiningOp()->getContainingRegion();
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// IRObjectWithUseList implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
Loading…
Reference in New Issue