Block *createBody();
/// Get the body of the AffineForOp.
- Block *getBody() { return &getBlockList().front(); }
- const Block *getBody() const { return &getBlockList().front(); }
+ Block *getBody() { return &getRegion().front(); }
+ const Block *getBody() const { return &getRegion().front(); }
- /// Get the blocklist containing the body.
- BlockList &getBlockList() { return getInstruction()->getBlockList(0); }
- const BlockList &getBlockList() const {
- return getInstruction()->getBlockList(0);
- }
+ /// Get the body region of the AffineForOp.
+ Region &getRegion() { return getInstruction()->getRegion(0); }
+ const Region &getRegion() const { return getInstruction()->getRegion(0); }
/// Returns the induction variable for this loop.
Value *getInductionVar();
IntegerSet getIntegerSet() const;
void setIntegerSet(IntegerSet newSet);
- /// Returns the list of 'then' blocks.
- BlockList &getThenBlocks();
- const BlockList &getThenBlocks() const {
+ /// Returns the 'then' region.
+ Region &getThenBlocks();
+ const Region &getThenBlocks() const {
return const_cast<AffineIfOp *>(this)->getThenBlocks();
}
- /// Returns the list of 'else' blocks.
- BlockList &getElseBlocks();
- const BlockList &getElseBlocks() const {
+ /// Returns the 'else' blocks.
+ Region &getElseBlocks();
+ const Region &getElseBlocks() const {
return const_cast<AffineIfOp *>(this)->getElseBlocks();
}
/// Recalculate the dominance info for the provided function.
void recalculate(Function *function);
- /// Get the root dominance node of the given block list.
- DominanceInfoNode *getRootNode(const BlockList *blockList) {
- assert(dominanceInfos.count(blockList) != 0);
- return dominanceInfos[blockList]->getRootNode();
+ /// Get the root dominance node of the given region.
+ DominanceInfoNode *getRootNode(const Region *region) {
+ assert(dominanceInfos.count(region) != 0);
+ return dominanceInfos[region]->getRootNode();
}
protected:
/// Return true if the specified block A properly dominates block B.
bool properlyDominates(const Block *a, const Block *b);
- /// A mapping of block lists to their base dominator tree.
- DenseMap<const BlockList *, std::unique_ptr<base>> dominanceInfos;
+ /// A mapping of regions to their base dominator tree.
+ DenseMap<const Region *, std::unique_ptr<base>> dominanceInfos;
};
} // end namespace detail
-//===- Block.h - MLIR Block and BlockList Classes ---------------*- C++ -*-===//
+//===- Block.h - MLIR Block and Region Classes ------------------*- C++ -*-===//
//
// Copyright 2019 The MLIR Authors.
//
// limitations under the License.
// =============================================================================
//
-// This file defines Block and BlockList classes.
+// This file defines Block and Region classes.
//
//===----------------------------------------------------------------------===//
namespace ilist_detail {
// Explicitly define the node access for the instruction list so that we can
// break the dependence on the Instruction class in this header. This allows for
-// instructions to have trailing BlockLists without a circular include
+// instructions to have trailing Regions without a circular include
// dependence.
template <>
struct SpecificNodeAccess<
namespace mlir {
class BlockAndValueMapping;
-class BlockList;
+class Region;
class Function;
using BlockOperand = IROperandImpl<Block>;
/// `Block` represents an ordered list of `Instruction`s.
class Block : public IRObjectWithUseList,
- public llvm::ilist_node_with_parent<Block, BlockList> {
+ public llvm::ilist_node_with_parent<Block, Region> {
public:
explicit Block() {}
~Block();
instructions.pop_back();
}
- /// Blocks are maintained in a list of BlockList type.
- BlockList *getParent() const { return parentValidInstOrderPair.getPointer(); }
+ /// Blocks are maintained in a Region.
+ Region *getParent() const { return parentValidInstOrderPair.getPointer(); }
/// Returns the closest surrounding instruction that contains this block or
/// nullptr if this is a top-level block.
private:
/// Pair of the parent object that owns this block and a bit that signifies if
/// the instructions within this block have a valid ordering.
- llvm::PointerIntPair<BlockList *, /*IntBits=*/1, bool>
- parentValidInstOrderPair;
+ llvm::PointerIntPair<Region *, /*IntBits=*/1, bool> parentValidInstOrderPair;
/// This is the list of instructions in the block.
InstListType instructions;
block_iterator first, block_iterator last);
private:
- mlir::BlockList *getContainingBlockList();
+ mlir::Region *getContainingRegion();
};
} // end namespace llvm
/// 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.
-class BlockList {
+class Region {
public:
- explicit BlockList(Function *container);
- explicit BlockList(Instruction *container);
+ explicit Region(Function *container);
+ explicit Region(Instruction *container);
- using BlockListType = llvm::iplist<Block>;
- BlockListType &getBlocks() { return blocks; }
- const BlockListType &getBlocks() const { return blocks; }
+ using RegionType = llvm::iplist<Block>;
+ RegionType &getBlocks() { return blocks; }
+ const RegionType &getBlocks() const { return blocks; }
// Iteration over the block in the function.
- using iterator = BlockListType::iterator;
- using const_iterator = BlockListType::const_iterator;
- using reverse_iterator = BlockListType::reverse_iterator;
- using const_reverse_iterator = BlockListType::const_reverse_iterator;
+ using iterator = RegionType::iterator;
+ using const_iterator = RegionType::const_iterator;
+ using reverse_iterator = RegionType::reverse_iterator;
+ using const_reverse_iterator = RegionType::const_reverse_iterator;
iterator begin() { return blocks.begin(); }
iterator end() { return blocks.end(); }
void push_front(Block *block) { blocks.push_front(block); }
Block &back() { return blocks.back(); }
- const Block &back() const { return const_cast<BlockList *>(this)->back(); }
+ const Block &back() const { return const_cast<Region *>(this)->back(); }
Block &front() { return blocks.front(); }
- const Block &front() const { return const_cast<BlockList *>(this)->front(); }
+ const Block &front() const { return const_cast<Region *>(this)->front(); }
- /// getSublistAccess() - Returns pointer to member of block list.
- static BlockListType BlockList::*getSublistAccess(Block *) {
- return &BlockList::blocks;
+ /// getSublistAccess() - Returns pointer to member of region.
+ static RegionType Region::*getSublistAccess(Block *) {
+ return &Region::blocks;
}
- /// A BlockList is part of a function or an operation region. If it is
- /// part of an operation region, then return the operation, otherwise return
- /// null.
+ /// 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.
Instruction *getContainingInst();
const Instruction *getContainingInst() const {
- return const_cast<BlockList *>(this)->getContainingInst();
+ return const_cast<Region *>(this)->getContainingInst();
}
- /// A BlockList is part of a function or an operation region. If it is part
- /// of a Function, then return it, otherwise return null.
+ /// A Region is either a function body or a part of an operation. If it is
+ /// a Function body, then return this function, otherwise return null.
Function *getContainingFunction();
const Function *getContainingFunction() const {
- return const_cast<BlockList *>(this)->getContainingFunction();
+ return const_cast<Region *>(this)->getContainingFunction();
}
- /// Clone the internal blocks from this block list into dest. Any
+ /// 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
/// in the respective cloned block.
- void cloneInto(BlockList *dest, BlockAndValueMapping &mapper,
+ void cloneInto(Region *dest, BlockAndValueMapping &mapper,
MLIRContext *context) const;
private:
- BlockListType blocks;
+ RegionType blocks;
/// This is the object we are part of.
llvm::PointerUnion<Function *, Instruction *> container;
// Body Handling
//===--------------------------------------------------------------------===//
- BlockList &getBlockList() { return blocks; }
- const BlockList &getBlockList() const { return blocks; }
+ Region &getBody() { return body; }
+ const Region &getBody() const { return body; }
/// This is the list of blocks in the function.
- using BlockListType = llvm::iplist<Block>;
- BlockListType &getBlocks() { return blocks.getBlocks(); }
- const BlockListType &getBlocks() const { return blocks.getBlocks(); }
+ using RegionType = llvm::iplist<Block>;
+ RegionType &getBlocks() { return body.getBlocks(); }
+ const RegionType &getBlocks() const { return body.getBlocks(); }
// Iteration over the block in the function.
- using iterator = BlockListType::iterator;
- using const_iterator = BlockListType::const_iterator;
- using reverse_iterator = BlockListType::reverse_iterator;
- using const_reverse_iterator = BlockListType::const_reverse_iterator;
-
- iterator begin() { return blocks.begin(); }
- iterator end() { return blocks.end(); }
- const_iterator begin() const { return blocks.begin(); }
- const_iterator end() const { return blocks.end(); }
- reverse_iterator rbegin() { return blocks.rbegin(); }
- reverse_iterator rend() { return blocks.rend(); }
- const_reverse_iterator rbegin() const { return blocks.rbegin(); }
- const_reverse_iterator rend() const { return blocks.rend(); }
-
- bool empty() const { return blocks.empty(); }
- void push_back(Block *block) { blocks.push_back(block); }
- void push_front(Block *block) { blocks.push_front(block); }
-
- Block &back() { return blocks.back(); }
+ using iterator = RegionType::iterator;
+ using const_iterator = RegionType::const_iterator;
+ using reverse_iterator = RegionType::reverse_iterator;
+ using const_reverse_iterator = RegionType::const_reverse_iterator;
+
+ iterator begin() { return body.begin(); }
+ iterator end() { return body.end(); }
+ const_iterator begin() const { return body.begin(); }
+ const_iterator end() const { return body.end(); }
+ reverse_iterator rbegin() { return body.rbegin(); }
+ reverse_iterator rend() { return body.rend(); }
+ const_reverse_iterator rbegin() const { return body.rbegin(); }
+ const_reverse_iterator rend() const { return body.rend(); }
+
+ bool empty() const { return body.empty(); }
+ void push_back(Block *block) { body.push_back(block); }
+ void push_front(Block *block) { body.push_front(block); }
+
+ Block &back() { return body.back(); }
const Block &back() const { return const_cast<Function *>(this)->back(); }
- Block &front() { return blocks.front(); }
+ Block &front() { return body.front(); }
const Block &front() const { return const_cast<Function *>(this)->front(); }
//===--------------------------------------------------------------------===//
/// The attributes lists for each of the function arguments.
std::vector<NamedAttributeList> argAttrs;
- /// The contents of the body.
- BlockList blocks;
+ /// The body of the function.
+ Region body;
void operator=(const Function &) = delete;
friend struct llvm::ilist_traits<Function>;
};
template <>
-struct GraphTraits<mlir::BlockList *> : public GraphTraits<mlir::Block *> {
- using GraphType = mlir::BlockList *;
+struct GraphTraits<mlir::Region *> : public GraphTraits<mlir::Block *> {
+ using GraphType = mlir::Region *;
using NodeRef = mlir::Block *;
static NodeRef getEntryNode(GraphType fn) { return &fn->front(); }
};
template <>
-struct GraphTraits<const mlir::BlockList *>
+struct GraphTraits<const mlir::Region *>
: public GraphTraits<const mlir::Block *> {
- using GraphType = const mlir::BlockList *;
+ using GraphType = const mlir::Region *;
using NodeRef = const mlir::Block *;
static NodeRef getEntryNode(GraphType fn) { return &fn->front(); }
};
template <>
-struct GraphTraits<Inverse<mlir::BlockList *>>
+struct GraphTraits<Inverse<mlir::Region *>>
: public GraphTraits<Inverse<mlir::Block *>> {
- using GraphType = Inverse<mlir::BlockList *>;
+ using GraphType = Inverse<mlir::Region *>;
using NodeRef = NodeRef;
static NodeRef getEntryNode(GraphType fn) { return &fn.Graph->front(); }
};
template <>
-struct GraphTraits<Inverse<const mlir::BlockList *>>
+struct GraphTraits<Inverse<const mlir::Region *>>
: public GraphTraits<Inverse<const mlir::Block *>> {
- using GraphType = Inverse<const mlir::BlockList *>;
+ using GraphType = Inverse<const mlir::Region *>;
using NodeRef = NodeRef;
static NodeRef getEntryNode(GraphType fn) { return &fn.Graph->front(); }
class Instruction final
: public llvm::ilist_node_with_parent<Instruction, Block>,
private llvm::TrailingObjects<Instruction, InstResult, BlockOperand,
- unsigned, BlockList,
- detail::OperandStorage> {
+ unsigned, Region, detail::OperandStorage> {
public:
/// Create a new Instruction with the specific fields.
- static Instruction *
- create(Location location, OperationName name, ArrayRef<Value *> operands,
- ArrayRef<Type> resultTypes, ArrayRef<NamedAttribute> attributes,
- ArrayRef<Block *> successors, unsigned numBlockLists,
- bool resizableOperandList, MLIRContext *context);
+ static Instruction *create(Location location, OperationName name,
+ ArrayRef<Value *> operands,
+ ArrayRef<Type> resultTypes,
+ ArrayRef<NamedAttribute> attributes,
+ ArrayRef<Block *> successors, unsigned numRegions,
+ bool resizableOperandList, MLIRContext *context);
/// The name of an operation is the key identifier for it.
OperationName getName() const { return name; }
// Blocks
//===--------------------------------------------------------------------===//
- /// Returns the number of block lists held by this operation.
- unsigned getNumBlockLists() const { return numBlockLists; }
+ /// Returns the number of regions held by this operation.
+ unsigned getNumRegions() const { return numRegions; }
- /// Returns the block lists held by this operation.
- MutableArrayRef<BlockList> getBlockLists() {
- return {getTrailingObjects<BlockList>(), numBlockLists};
+ /// Returns the regions held by this operation.
+ MutableArrayRef<Region> getRegions() {
+ return {getTrailingObjects<Region>(), numRegions};
}
- ArrayRef<BlockList> getBlockLists() const {
- return const_cast<Instruction *>(this)->getBlockLists();
+ ArrayRef<Region> getRegions() const {
+ return const_cast<Instruction *>(this)->getRegions();
}
- /// Returns the block list held by this operation at position 'index'.
- BlockList &getBlockList(unsigned index) {
- assert(index < numBlockLists && "invalid block list index");
- return getBlockLists()[index];
+ /// Returns the region held by this operation at position 'index'.
+ Region &getRegion(unsigned index) {
+ assert(index < numRegions && "invalid region index");
+ return getRegions()[index];
}
- const BlockList &getBlockList(unsigned index) const {
- return const_cast<Instruction *>(this)->getBlockList(index);
+ const Region &getRegion(unsigned index) const {
+ return const_cast<Instruction *>(this)->getRegion(index);
}
//===--------------------------------------------------------------------===//
protected:
Instruction(Location location, OperationName name, unsigned numResults,
- unsigned numSuccessors, unsigned numBlockLists,
+ unsigned numSuccessors, unsigned numRegions,
ArrayRef<NamedAttribute> attributes, MLIRContext *context);
// Instructions are deleted through the destroy() member because they are
/// O(1) local dominance checks between instructions.
mutable unsigned orderIndex = 0;
- const unsigned numResults, numSuccs, numBlockLists;
+ const unsigned numResults, numSuccs, numRegions;
/// This holds the name of the operation.
OperationName name;
// This stuff is used by the TrailingObjects template.
friend llvm::TrailingObjects<Instruction, InstResult, BlockOperand, unsigned,
- BlockList, detail::OperandStorage>;
+ Region, detail::OperandStorage>;
size_t numTrailingObjects(OverloadToken<InstResult>) const {
return numResults;
}
size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
return numSuccs;
}
- size_t numTrailingObjects(OverloadToken<BlockList>) const {
- return numBlockLists;
- }
+ size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
size_t numTrailingObjects(OverloadToken<unsigned>) const { return numSuccs; }
};
/// Print the entire operation with the default generic assembly form.
virtual void printGenericOp(const Instruction *op) = 0;
- /// Prints a block list.
- virtual void printBlockList(const BlockList &blocks,
- bool printEntryBlockArgs = true) = 0;
+ /// Prints a region.
+ virtual void printRegion(const Region &blocks,
+ bool printEntryBlockArgs = true) = 0;
private:
OpAsmPrinter(const OpAsmPrinter &) = delete;
int requiredOperandCount = -1,
Delimiter delimiter = Delimiter::None) = 0;
- /// Parses a block list. Any parsed blocks are filled in to the
- /// operation's block lists after the operation is created.
- virtual bool parseBlockList() = 0;
+ /// Parses a region. Any parsed blocks are filled in to the operation's
+ /// regions after the operation is created.
+ virtual bool parseRegion() = 0;
- /// Parses an argument for the entry block of the next block list to be
- /// parsed.
- virtual bool parseBlockListEntryBlockArgument(Type argType) = 0;
+ /// Parses an argument for the entry block of the next region to be parsed.
+ virtual bool parseRegionEntryBlockArgument(Type argType) = 0;
//===--------------------------------------------------------------------===//
// Methods for interacting with the parser
SmallVector<NamedAttribute, 4> attributes;
/// Successors of this operation and their respective operands.
SmallVector<Block *, 1> successors;
- unsigned numBlockLists = 0;
+ unsigned numRegions = 0;
/// If the operation has a resizable operand list.
bool resizableOperandList = false;
OperationState(MLIRContext *context, Location location, StringRef name,
ArrayRef<Value *> operands, ArrayRef<Type> types,
ArrayRef<NamedAttribute> attributes,
- ArrayRef<Block *> successors = {}, unsigned numBlockLists = 0,
+ ArrayRef<Block *> successors = {}, unsigned numRegions = 0,
bool resizableOperandList = false)
: context(context), location(location), name(name, context),
operands(operands.begin(), operands.end()),
types(types.begin(), types.end()),
attributes(attributes.begin(), attributes.end()),
successors(successors.begin(), successors.end()),
- numBlockLists(numBlockLists) {}
+ numRegions(numRegions) {}
void addOperands(ArrayRef<Value *> newOperands) {
assert(successors.empty() &&
operands.append(succOperands.begin(), succOperands.end());
}
- /// Add a new block list with the specified blocks.
- void reserveBlockLists(unsigned numReserved) { numBlockLists += numReserved; }
+ /// Reserve space for new regions.
+ void reserveRegions(unsigned numReserved) { numRegions += numReserved; }
/// Sets the operand list of the operation as resizable.
void setOperandListToResizable(bool isResizable = true) {
builder->getAffineMapAttr(ubMap));
result->addOperands(ubOperands);
- // Reserve a block list for the body.
- result->reserveBlockLists(/*numReserved=*/1);
+ // Reserve a region for the body.
+ result->reserveRegions(/*numReserved=*/1);
// Set the operands list as resizable so that we can freely modify the bounds.
result->setOperandListToResizable();
}
bool AffineForOp::verify() const {
- const auto &bodyBlockList = getInstruction()->getBlockList(0);
+ const auto &bodyRegion = getInstruction()->getRegion(0);
- // The body block list must contain a single basic block.
- if (bodyBlockList.empty() ||
- std::next(bodyBlockList.begin()) != bodyBlockList.end())
- return emitOpError("expected body block list to have a single block");
+ // The body region must contain a single basic block.
+ if (bodyRegion.empty() || std::next(bodyRegion.begin()) != bodyRegion.end())
+ return emitOpError("expected body region to have a single block");
// Check that the body defines as single block argument for the induction
// variable.
bool AffineForOp::parse(OpAsmParser *parser, OperationState *result) {
auto &builder = parser->getBuilder();
// Parse the induction variable followed by '='.
- if (parser->parseBlockListEntryBlockArgument(builder.getIndexType()) ||
+ if (parser->parseRegionEntryBlockArgument(builder.getIndexType()) ||
parser->parseEqual())
return true;
"expected step to be representable as a positive signed integer");
}
- // Parse the body block list.
- result->reserveBlockLists(/*numReserved=*/1);
- if (parser->parseBlockList())
+ // Parse the body region.
+ result->reserveRegions(/*numReserved=*/1);
+ if (parser->parseRegion())
return true;
// Parse the optional attribute list.
if (getStep() != 1)
*p << " step " << getStep();
- p->printBlockList(getInstruction()->getBlockList(0),
- /*printEntryBlockArgs=*/false);
+ p->printRegion(getInstruction()->getRegion(0),
+ /*printEntryBlockArgs=*/false);
p->printOptionalAttrDict(getAttrs(),
/*elidedAttrs=*/{getLowerBoundAttrName(),
getUpperBoundAttrName(),
}
Block *AffineForOp::createBody() {
- auto &bodyBlockList = getBlockList();
- assert(bodyBlockList.empty() && "expected no existing body blocks");
+ auto &bodyRegion = getRegion();
+ assert(bodyRegion.empty() && "expected no existing body blocks");
// Create a new block for the body, and add an argument for the induction
// variable.
Block *body = new Block();
body->addArgument(IndexType::get(getInstruction()->getContext()));
- bodyBlockList.push_back(body);
+ bodyRegion.push_back(body);
return body;
}
result->addAttribute(getConditionAttrName(), IntegerSetAttr::get(condition));
result->addOperands(conditionOperands);
- // Reserve 2 block lists, one for the 'then' and one for the 'else' regions.
- result->reserveBlockLists(2);
+ // Reserve 2 regions, one for the 'then' and one for the 'else' regions.
+ result->reserveRegions(2);
}
bool AffineIfOp::verify() const {
condition.getNumDims()))
return true;
- // Verify that the entry of each child blocklist does not have arguments.
- for (const auto &blockList : getInstruction()->getBlockLists()) {
- if (blockList.empty())
+ // Verify that the entry of each child region does not have arguments.
+ for (const auto ®ion : getInstruction()->getRegions()) {
+ if (region.empty())
continue;
// TODO(riverriddle) We currently do not allow multiple blocks in child
- // block lists.
- if (std::next(blockList.begin()) != blockList.end())
- return emitOpError(
- "expects only one block per 'then' or 'else' block list");
- if (blockList.front().back().isKnownTerminator())
+ // regions.
+ if (std::next(region.begin()) != region.end())
+ return emitOpError("expects only one block per 'then' or 'else' regions");
+ if (region.front().back().isKnownTerminator())
return emitOpError("expects region block to not have a terminator");
- for (const auto &b : blockList)
+ for (const auto &b : region)
if (b.getNumArguments() != 0)
return emitOpError(
"requires that child entry blocks have no arguments");
parser->getNameLoc(),
"symbol operand count and integer set symbol count must match");
- // Parse the 'then' block list.
- if (parser->parseBlockList())
+ // Parse the 'then' region.
+ if (parser->parseRegion())
return true;
- // If we find an 'else' keyword then parse the else block list.
+ // If we find an 'else' keyword then parse the 'else' region.
if (!parser->parseOptionalKeyword("else")) {
- if (parser->parseBlockList())
+ if (parser->parseRegion())
return true;
}
if (parser->parseOptionalAttributeDict(result->attributes))
return true;
- // Reserve 2 block lists, one for the 'then' and one for the 'else' regions.
- result->reserveBlockLists(2);
+ // Reserve 2 regions, one for the 'then' and one for the 'else' regions.
+ result->reserveRegions(2);
return false;
}
*p << "if " << conditionAttr;
printDimAndSymbolList(operand_begin(), operand_end(),
conditionAttr.getValue().getNumDims(), p);
- p->printBlockList(getInstruction()->getBlockList(0));
+ p->printRegion(getInstruction()->getRegion(0));
- // Print the 'else' block list if it has any blocks.
- const auto &elseBlockList = getInstruction()->getBlockList(1);
- if (!elseBlockList.empty()) {
+ // Print the 'else' regions if it has any blocks.
+ const auto &elseRegion = getInstruction()->getRegion(1);
+ if (!elseRegion.empty()) {
*p << " else";
- p->printBlockList(elseBlockList);
+ p->printRegion(elseRegion);
}
// Print the attribute list.
}
/// Returns the list of 'then' blocks.
-BlockList &AffineIfOp::getThenBlocks() {
- return getInstruction()->getBlockList(0);
-}
+Region &AffineIfOp::getThenBlocks() { return getInstruction()->getRegion(0); }
/// Returns the list of 'else' blocks.
-BlockList &AffineIfOp::getElseBlocks() {
- return getInstruction()->getBlockList(1);
-}
+Region &AffineIfOp::getElseBlocks() { return getInstruction()->getRegion(1); }
// Build the top level function dominance.
auto functionDominance = std::make_unique<base>();
- functionDominance->recalculate(function->getBlockList());
- dominanceInfos.try_emplace(&function->getBlockList(),
+ functionDominance->recalculate(function->getBody());
+ dominanceInfos.try_emplace(&function->getBody(),
std::move(functionDominance));
- /// Build the dominance for each of the internal region block lists.
+ /// Build the dominance for each of the operation regions.
function->walk([&](Instruction *inst) {
- for (auto &blockList : inst->getBlockLists()) {
+ for (auto ®ion : inst->getRegions()) {
// Don't compute dominance if the region is empty.
- if (blockList.empty())
+ if (region.empty())
continue;
auto opDominance = std::make_unique<base>();
- opDominance->recalculate(blockList);
- dominanceInfos.try_emplace(&blockList, std::move(opDominance));
+ opDominance->recalculate(region);
+ dominanceInfos.try_emplace(®ion, std::move(opDominance));
}
});
}
if (a == b)
return false;
- // If both blocks are not in the same block list, 'a' properly dominates 'b'
- // if 'b' is defined in an instruction region that (recursively) ends up being
+ // If both blocks are not in the same region, 'a' properly dominates 'b' if
+ // 'b' is defined in an instruction region that (recursively) ends up being
// dominated by 'a'. Walk up the list of containers enclosing B.
- auto *blockListA = a->getParent(), *blockListB = b->getParent();
- if (blockListA != blockListB) {
+ auto *regionA = a->getParent(), *regionB = b->getParent();
+ if (regionA != regionB) {
Instruction *bAncestor;
do {
- bAncestor = blockListB->getContainingInst();
+ bAncestor = regionB->getContainingInst();
// If 'bAncestor' is the top level function, then 'a' is a block
// that post dominates 'b'.
if (!bAncestor)
return IsPostDom;
- blockListB = bAncestor->getBlock()->getParent();
- } while (blockListA != blockListB);
+ regionB = bAncestor->getBlock()->getParent();
+ } while (regionA != regionB);
// Check to see if the ancestor of 'b' is the same block as 'a'.
b = bAncestor->getBlock();
}
// Otherwise, use the standard dominance functionality.
- auto baseInfoIt = dominanceInfos.find(blockListA);
- assert(baseInfoIt != dominanceInfos.end() && "block list info not found");
+ auto baseInfoIt = dominanceInfos.find(regionA);
+ assert(baseInfoIt != dominanceInfos.end() && "region info not found");
return baseInfoIt->second->properlyDominates(a, b);
}
// No vectorization across unknown regions.
auto regions = matcher::Op([](const Instruction &inst) -> bool {
- return inst.getNumBlockLists() != 0 &&
+ return inst.getNumRegions() != 0 &&
!(inst.isa<AffineIfOp>() || inst.isa<AffineForOp>());
});
SmallVector<NestedMatch, 8> regionsMatched;
return getInstAtPosition(positions, level + 1,
childAffineForOp->getBody());
- for (auto &blockList : inst.getBlockLists()) {
- for (auto &b : blockList)
+ for (auto ®ion : inst.getRegions()) {
+ for (auto &b : region)
if (auto *ret = getInstAtPosition(positions, level + 1, &b))
return ret;
}
}
// Verify that all child blocks are ok.
- for (auto &blockList : op.getBlockLists())
- for (auto &b : blockList)
+ for (auto ®ion : op.getRegions())
+ for (auto &b : region)
if (verifyBlock(b, /*isTopLevel=*/false))
return true;
}
// Verify the dominance of each of the nested blocks within this instruction.
- for (auto &blockList : inst.getBlockLists())
- for (auto &block : blockList)
+ for (auto ®ion : inst.getRegions())
+ for (auto &block : region)
if (verifyDominance(block))
return true;
void printSuccessorAndUseList(const Instruction *term,
unsigned index) override;
- /// Print a block list.
- void printBlockList(const BlockList &blocks,
- bool printEntryBlockArgs) override {
+ /// Print a region.
+ void printRegion(const Region &blocks, bool printEntryBlockArgs) override {
os << " {\n";
if (!blocks.empty()) {
auto *entryBlock = &blocks.front();
numberValuesInBlock(block);
}
-/// Number all of the SSA values in the specified block list.
+/// Number all of the SSA values in the specified block. Values get numbered
+/// continuously throughout regions. In particular, we traverse the regions
+/// held by operations and number values in depth-first pre-order.
void FunctionPrinter::numberValuesInBlock(const Block &block) {
// Each block gets a unique ID, and all of the instructions within it get
// numbered as well.
// result.
if (inst.getNumResults() != 0)
numberValueID(inst.getResult(0));
- for (auto &blockList : inst.getBlockLists())
- for (const auto &block : blockList)
+ for (auto ®ion : inst.getRegions())
+ for (const auto &block : region)
numberValuesInBlock(block);
}
}
// argument is to an entry block of an operation region, give it an 'i'
// name.
if (auto *block = cast<BlockArgument>(value)->getOwner()) {
- auto *parentBlockList = block->getParent();
- if (parentBlockList && block == &parentBlockList->front()) {
- if (parentBlockList->getContainingFunction())
+ auto *parentRegion = block->getParent();
+ if (parentRegion && block == &parentRegion->front()) {
+ if (parentRegion->getContainingFunction())
specialName << "arg" << nextArgumentID++;
else
specialName << "i" << nextRegionArgumentID++;
printTrailingLocation(function->getLoc());
if (!function->empty()) {
- printBlockList(function->getBlockList(), /*printEntryBlockArgs=*/false);
+ printRegion(function->getBody(), /*printEntryBlockArgs=*/false);
os << "\n";
}
os << '\n';
os << ')';
}
- // Print any trailing block lists.
- for (auto &blockList : op->getBlockLists())
- printBlockList(blockList, /*printEntryBlockArgs=*/true);
+ // Print any trailing regions.
+ for (auto ®ion : op->getRegions())
+ printRegion(region, /*printEntryBlockArgs=*/true);
}
void FunctionPrinter::printSuccessorAndUseList(const Instruction *term,
-//===- Block.cpp - MLIR Block and BlockList Classes -----------------------===//
+//===- Block.cpp - MLIR Block and Region Classes --------------------------===//
//
// Copyright 2019 The MLIR Authors.
//
void Block::insertBefore(Block *block) {
assert(!getParent() && "already inserted into a block!");
assert(block->getParent() && "cannot insert before a block without a parent");
- block->getParent()->getBlocks().insert(BlockList::iterator(block), this);
+ block->getParent()->getBlocks().insert(Region::iterator(block), this);
}
/// Unlink this Block from its Function and delete it.
}
//===----------------------------------------------------------------------===//
-// BlockList
+// Region
//===----------------------------------------------------------------------===//
-BlockList::BlockList(Function *container) : container(container) {}
+Region::Region(Function *container) : container(container) {}
-BlockList::BlockList(Instruction *container) : container(container) {}
+Region::Region(Instruction *container) : container(container) {}
-Instruction *BlockList::getContainingInst() {
+Instruction *Region::getContainingInst() {
return container.dyn_cast<Instruction *>();
}
-Function *BlockList::getContainingFunction() {
+Function *Region::getContainingFunction() {
return container.dyn_cast<Function *>();
}
-/// Clone the internal blocks from this block list into dest. Any
+/// Clone the internal blocks from this region into `dest`. Any
/// cloned blocks are appended to the back of dest.
-void BlockList::cloneInto(BlockList *dest, BlockAndValueMapping &mapper,
- MLIRContext *context) const {
- assert(dest && "expected valid block list to clone into");
+void Region::cloneInto(Region *dest, BlockAndValueMapping &mapper,
+ MLIRContext *context) const {
+ assert(dest && "expected valid region to clone into");
// If the list is empty there is nothing to clone.
if (empty())
it->walk(remapOperands);
}
-BlockList *llvm::ilist_traits<::mlir::Block>::getContainingBlockList() {
+Region *llvm::ilist_traits<::mlir::Block>::getContainingRegion() {
size_t Offset(
- size_t(&((BlockList *)nullptr->*BlockList::getSublistAccess(nullptr))));
+ size_t(&((Region *)nullptr->*Region::getSublistAccess(nullptr))));
iplist<Block> *Anchor(static_cast<iplist<Block> *>(this));
- return reinterpret_cast<BlockList *>(reinterpret_cast<char *>(Anchor) -
- Offset);
+ return reinterpret_cast<Region *>(reinterpret_cast<char *>(Anchor) - Offset);
}
-/// This is a trait method invoked when a basic block is added to a function.
-/// We keep the function pointer up to date.
+/// This is a trait method invoked when a basic block is added to a region.
+/// We keep the region pointer up to date.
void llvm::ilist_traits<::mlir::Block>::addNodeToList(Block *block) {
- assert(!block->getParent() && "already in a function!");
- block->parentValidInstOrderPair.setPointer(getContainingBlockList());
+ assert(!block->getParent() && "already in a region!");
+ block->parentValidInstOrderPair.setPointer(getContainingRegion());
}
/// This is a trait method invoked when an instruction is removed from a
-/// function. We keep the function pointer up to date.
+/// region. We keep the region pointer up to date.
void llvm::ilist_traits<::mlir::Block>::removeNodeFromList(Block *block) {
- assert(block->getParent() && "not already in a function!");
+ assert(block->getParent() && "not already in a region!");
block->parentValidInstOrderPair.setPointer(nullptr);
}
ilist_traits<Block> &otherList, block_iterator first, block_iterator last) {
// If we are transferring instructions within the same function, the parent
// pointer doesn't need to be updated.
- auto *curParent = getContainingBlockList();
- if (curParent == otherList.getContainingBlockList())
+ auto *curParent = getContainingRegion();
+ if (curParent == otherList.getContainingRegion())
return;
// Update the 'parent' member of each Block.
/// Create an operation given the fields represented as an OperationState.
Instruction *FuncBuilder::createOperation(const OperationState &state) {
assert(block && "createOperation() called without setting builder's block");
- auto *op = Instruction::create(state.location, state.name, state.operands,
- state.types, state.attributes,
- state.successors, state.numBlockLists,
- state.resizableOperandList, context);
+ auto *op = Instruction::create(
+ state.location, state.name, state.operands, state.types, state.attributes,
+ state.successors, state.numRegions, state.resizableOperandList, context);
block->getInstructions().insert(insertPoint, op);
return op;
}
ArrayRef<NamedAttribute> attrs)
: name(Identifier::get(name, type.getContext())), location(location),
type(type), attrs(type.getContext(), attrs),
- argAttrs(type.getNumInputs()), blocks(this) {}
+ argAttrs(type.getNumInputs()), body(this) {}
Function::Function(Location location, StringRef name, FunctionType type,
ArrayRef<NamedAttribute> attrs,
ArrayRef<NamedAttributeList> argAttrs)
: name(Identifier::get(name, type.getContext())), location(location),
type(type), attrs(type.getContext(), attrs), argAttrs(argAttrs),
- blocks(this) {}
+ body(this) {}
Function::~Function() {
// Instructions may have cyclic references, which need to be dropped before we
}
dest->setAttrs(newAttrs.takeVector());
- // Clone the block list.
- blocks.cloneInto(&dest->blocks, mapper, dest->getContext());
+ // Clone the body.
+ body.cloneInto(&dest->body, mapper, dest->getContext());
}
/// Create a deep copy of this function and all of its blocks, remapping
//===----------------------------------------------------------------------===//
/// Create a new Instruction with the specific fields.
-Instruction *
-Instruction::create(Location location, OperationName name,
- ArrayRef<Value *> operands, ArrayRef<Type> resultTypes,
- ArrayRef<NamedAttribute> attributes,
- ArrayRef<Block *> successors, unsigned numBlockLists,
- bool resizableOperandList, MLIRContext *context) {
+Instruction *Instruction::create(Location location, OperationName name,
+ ArrayRef<Value *> operands,
+ ArrayRef<Type> resultTypes,
+ ArrayRef<NamedAttribute> attributes,
+ ArrayRef<Block *> successors,
+ unsigned numRegions, bool resizableOperandList,
+ MLIRContext *context) {
unsigned numSuccessors = successors.size();
// Input operands are nullptr-separated for each successor, the null operands
unsigned numOperands = operands.size() - numSuccessors;
// Compute the byte size for the instruction and the operand storage.
- auto byteSize = totalSizeToAlloc<InstResult, BlockOperand, unsigned,
- BlockList, detail::OperandStorage>(
- resultTypes.size(), numSuccessors, numSuccessors, numBlockLists,
+ auto byteSize = totalSizeToAlloc<InstResult, BlockOperand, unsigned, Region,
+ detail::OperandStorage>(
+ resultTypes.size(), numSuccessors, numSuccessors, numRegions,
/*detail::OperandStorage*/ 1);
byteSize += llvm::alignTo(detail::OperandStorage::additionalAllocSize(
numOperands, resizableOperandList),
// Create the new Instruction.
auto inst = ::new (rawMem)
- Instruction(location, name, resultTypes.size(), numSuccessors,
- numBlockLists, attributes, context);
+ Instruction(location, name, resultTypes.size(), numSuccessors, numRegions,
+ attributes, context);
assert((numSuccessors == 0 || !inst->isKnownNonTerminator()) &&
"unexpected successors in a non-terminator operation");
- // Initialize the block lists.
- for (unsigned i = 0; i != numBlockLists; ++i)
- new (&inst->getBlockList(i)) BlockList(inst);
+ // Initialize the regions.
+ for (unsigned i = 0; i != numRegions; ++i)
+ new (&inst->getRegion(i)) Region(inst);
// Initialize the results and operands.
new (&inst->getOperandStorage())
Instruction::Instruction(Location location, OperationName name,
unsigned numResults, unsigned numSuccessors,
- unsigned numBlockLists,
+ unsigned numRegions,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
: location(location), numResults(numResults), numSuccs(numSuccessors),
- numBlockLists(numBlockLists), name(name), attrs(context, attributes) {}
+ numRegions(numRegions), name(name), attrs(context, attributes) {}
// Instructions are deleted through the destroy() member because they are
// allocated via malloc.
for (auto &successor : getBlockOperands())
successor.~BlockOperand();
- // Explicitly destroy the block list.
- for (auto &blockList : getBlockLists())
- blockList.~BlockList();
+ // Explicitly destroy the regions.
+ for (auto ®ion : getRegions())
+ region.~Region();
}
/// Destroy this instruction or one of its subclasses.
callback(this);
// Visit any internal instructions.
- for (auto &blockList : getBlockLists())
- for (auto &block : blockList)
+ for (auto ®ion : getRegions())
+ for (auto &block : region)
block.walk(callback);
}
void Instruction::walkPostOrder(
const std::function<void(Instruction *)> &callback) {
// Visit any internal instructions.
- for (auto &blockList : llvm::reverse(getBlockLists()))
- for (auto &block : llvm::reverse(blockList))
+ for (auto ®ion : llvm::reverse(getRegions()))
+ for (auto &block : llvm::reverse(region))
block.walkPostOrder(callback);
// Visit the current instruction.
for (auto &op : getInstOperands())
op.drop();
- for (auto &blockList : getBlockLists())
- for (Block &block : blockList)
+ for (auto ®ion : getRegions())
+ for (Block &block : region)
block.dropAllReferences();
for (auto &dest : getBlockOperands())
for (auto *result : getResults())
resultTypes.push_back(result->getType());
- unsigned numBlockLists = getNumBlockLists();
+ unsigned numRegions = getNumRegions();
auto *newOp = Instruction::create(getLoc(), getName(), operands, resultTypes,
- getAttrs(), successors, numBlockLists,
+ getAttrs(), successors, numRegions,
hasResizableOperandsList(), context);
- // Clone the block lists.
- for (unsigned i = 0; i != numBlockLists; ++i)
- getBlockList(i).cloneInto(&newOp->getBlockList(i), mapper, context);
+ // Clone the regions.
+ for (unsigned i = 0; i != numRegions; ++i)
+ getRegion(i).cloneInto(&newOp->getRegion(i), mapper, context);
// Remember the mapping of any results.
for (unsigned i = 0, e = getNumResults(); i != e; ++i)
// Block references.
ParseResult
- parseOperationBlockList(SmallVectorImpl<Block *> &results,
- ArrayRef<std::pair<SSAUseInfo, Type>> entryArguments);
- ParseResult parseBlockListBody(SmallVectorImpl<Block *> &results);
+ parseOperationRegion(SmallVectorImpl<Block *> &results,
+ ArrayRef<std::pair<SSAUseInfo, Type>> entryArguments);
+ ParseResult parseRegionBody(SmallVectorImpl<Block *> &results);
ParseResult parseBlock(Block *&block);
ParseResult parseBlockBody(Block *block);
// Parse the remaining list of blocks.
SmallVector<Block *, 16> blocks;
- if (parseBlockListBody(blocks))
+ if (parseRegionBody(blocks))
return ParseFailure;
function->getBlocks().insert(function->end(), blocks.begin(), blocks.end());
///
/// block-list ::= '{' block-list-body
///
-ParseResult FunctionParser::parseOperationBlockList(
+ParseResult FunctionParser::parseOperationRegion(
SmallVectorImpl<Block *> &results,
ArrayRef<std::pair<FunctionParser::SSAUseInfo, Type>> entryArguments) {
// Parse the '{'.
- if (parseToken(Token::l_brace, "expected '{' to begin block list"))
+ if (parseToken(Token::l_brace, "expected '{' to begin a region"))
return ParseFailure;
- // Check for an empty block list.
+ // Check for an empty region.
if (entryArguments.empty() && consumeIf(Token::r_brace))
return ParseSuccess;
Block *currentBlock = builder.getInsertionBlock();
return emitError("entry block arguments were already defined");
}
- // Parse the rest of the block list.
+ // Parse the rest of the region.
results.push_back(block);
- if (parseBlockListBody(results))
+ if (parseRegionBody(results))
return ParseFailure;
// Reset insertion point to the current block.
return ParseSuccess;
}
-/// Block list.
+/// Region.
///
-/// block-list-body ::= block* '}'
+/// region-body ::= block* '}'
///
-ParseResult
-FunctionParser::parseBlockListBody(SmallVectorImpl<Block *> &results) {
- // Parse the block list.
+ParseResult FunctionParser::parseRegionBody(SmallVectorImpl<Block *> &results) {
+ // Parse the list of blocks.
while (!consumeIf(Token::r_brace)) {
Block *newBlock = nullptr;
if (parseBlock(newBlock)) {
auto name = OperationName("placeholder", getContext());
auto *inst = Instruction::create(
getEncodedSourceLocation(loc), name, /*operands=*/{}, type,
- /*attributes=*/{}, /*successors=*/{}, /*numBlockLists=*/0,
+ /*attributes=*/{}, /*successors=*/{}, /*numRegions=*/0,
/*resizableOperandList=*/false, getContext());
forwardReferencePlaceholders[inst->getResult(0)] = loc;
return inst->getResult(0);
result.addSuccessor(successor, operands);
}
- // Parse the optional block lists for this operation.
+ // Parse the optional regions for this operation.
std::vector<SmallVector<Block *, 2>> blocks;
while (getToken().is(Token::l_brace)) {
SmallVector<Block *, 2> newBlocks;
- if (parseOperationBlockList(newBlocks, /*entryArguments=*/llvm::None)) {
- for (auto &blockList : blocks)
- cleanupInvalidBlocks(blockList);
+ if (parseOperationRegion(newBlocks, /*entryArguments=*/llvm::None)) {
+ for (auto ®ion : blocks)
+ cleanupInvalidBlocks(region);
return nullptr;
}
blocks.emplace_back(newBlocks);
}
- result.reserveBlockLists(blocks.size());
+ result.reserveRegions(blocks.size());
auto *opInst = builder.createOperation(result);
- // Initialize the parsed block lists.
+ // Initialize the parsed regions.
for (unsigned i = 0, e = blocks.size(); i != e; ++i) {
- auto &blockList = opInst->getBlockList(i).getBlocks();
- blockList.insert(blockList.end(), blocks[i].begin(), blocks[i].end());
+ auto ®ion = opInst->getRegion(i).getBlocks();
+ region.insert(region.end(), blocks[i].begin(), blocks[i].end());
}
return opInst;
}
if (opDefinition->parseAssembly(this, opState))
return true;
- // Check that enough block lists were reserved for those that were parsed.
- if (parsedBlockLists.size() > opState->numBlockLists) {
+ // Check that enough regions were reserved for those that were parsed.
+ if (parsedRegions.size() > opState->numRegions) {
return emitError(
nameLoc,
- "parsed more block lists than those reserved in the operation state");
+ "parsed more regions than those reserved in the operation state");
}
// Check there were no dangling entry block arguments.
- if (!parsedBlockListEntryArguments.empty()) {
+ if (!parsedRegionEntryArguments.empty()) {
return emitError(
- nameLoc,
- "no block list was attached to parsed entry block arguments");
+ nameLoc, "no region was attached to parsed entry block arguments");
}
// Check that none of the operands of the current operation reference an
- // entry block argument for any of the block lists.
- for (auto *entryArg : parsedBlockListEntryArgumentPlaceholders)
+ // entry block argument for any of the region.
+ for (auto *entryArg : parsedRegionEntryArgumentPlaceholders)
if (llvm::is_contained(opState->operands, entryArg))
return emitError(nameLoc, "operand use before it's defined");
return result == nullptr;
}
- /// Parses a list of blocks.
- bool parseBlockList() override {
- // Parse the block list.
+ /// Parses a region.
+ bool parseRegion() override {
SmallVector<Block *, 2> results;
- if (parser.parseOperationBlockList(results, parsedBlockListEntryArguments))
+ if (parser.parseOperationRegion(results, parsedRegionEntryArguments))
return true;
- parsedBlockListEntryArguments.clear();
- parsedBlockLists.emplace_back(results);
+ parsedRegionEntryArguments.clear();
+ parsedRegions.emplace_back(results);
return false;
}
- /// Parses an argument for the entry block of the next block list to be
- /// parsed.
- bool parseBlockListEntryBlockArgument(Type argType) override {
+ /// Parses an argument for the entry block of the next region to be parsed.
+ bool parseRegionEntryBlockArgument(Type argType) override {
SmallVector<Value *, 1> argValues;
OperandType operand;
if (parseOperand(operand))
FunctionParser::SSAUseInfo operandInfo = {operand.name, operand.number,
operand.location};
if (auto *value = parser.resolveSSAUse(operandInfo, argType)) {
- parsedBlockListEntryArguments.emplace_back(operandInfo, argType);
+ parsedRegionEntryArguments.emplace_back(operandInfo, argType);
// Track each of the placeholders so that we can detect invalid references
- // to block list arguments.
- parsedBlockListEntryArgumentPlaceholders.emplace_back(value);
+ // to region arguments.
+ parsedRegionEntryArgumentPlaceholders.emplace_back(value);
return false;
}
/// Emit a diagnostic at the specified location and return true.
bool emitError(llvm::SMLoc loc, const Twine &message) override {
- // If we emit an error, then cleanup any parsed block lists.
- for (auto &blockList : parsedBlockLists)
- parser.cleanupInvalidBlocks(blockList);
- parsedBlockLists.clear();
+ // If we emit an error, then cleanup any parsed regions.
+ for (auto ®ion : parsedRegions)
+ parser.cleanupInvalidBlocks(region);
+ parsedRegions.clear();
parser.emitError(loc, "custom op '" + Twine(opName) + "' " + message);
emittedError = true;
bool didEmitError() const { return emittedError; }
- /// Returns the block lists that were parsed.
- MutableArrayRef<SmallVector<Block *, 2>> getParsedBlockLists() {
- return parsedBlockLists;
+ /// Returns the regions that were parsed.
+ MutableArrayRef<SmallVector<Block *, 2>> getParsedRegions() {
+ return parsedRegions;
}
private:
- std::vector<SmallVector<Block *, 2>> parsedBlockLists;
+ std::vector<SmallVector<Block *, 2>> parsedRegions;
SmallVector<std::pair<FunctionParser::SSAUseInfo, Type>, 2>
- parsedBlockListEntryArguments;
- SmallVector<Value *, 2> parsedBlockListEntryArgumentPlaceholders;
+ parsedRegionEntryArguments;
+ SmallVector<Value *, 2> parsedRegionEntryArgumentPlaceholders;
SMLoc nameLoc;
StringRef opName;
FunctionParser &parser;
// Otherwise, we succeeded. Use the state it parsed as our op information.
auto *opInst = builder.createOperation(opState);
- // Resolve any parsed block lists.
- auto parsedBlockLists = opAsmParser.getParsedBlockLists();
- for (unsigned i = 0, e = parsedBlockLists.size(); i != e; ++i) {
- auto &opBlockList = opInst->getBlockList(i).getBlocks();
- opBlockList.insert(opBlockList.end(), parsedBlockLists[i].begin(),
- parsedBlockLists[i].end());
+ // Resolve any parsed regions.
+ auto parsedRegions = opAsmParser.getParsedRegions();
+ for (unsigned i = 0, e = parsedRegions.size(); i != e; ++i) {
+ auto &opRegion = opInst->getRegion(i).getBlocks();
+ opRegion.insert(opRegion.end(), parsedRegions[i].begin(),
+ parsedRegions[i].end());
}
return opInst;
}
bool simplifyOperation(Instruction *op);
void simplifyBlock(DominanceInfo &domInfo, Block *bb);
- void simplifyBlockList(DominanceInfo &domInfo, BlockList &blockList);
+ void simplifyRegion(DominanceInfo &domInfo, Region ®ion);
void runOnFunction() override;
// Don't simplify operations with nested blocks. We don't currently model
// equality comparisons correctly among other things. It is also unclear
// whether we would want to CSE such operations.
- if (op->getNumBlockLists() != 0)
+ if (op->getNumRegions() != 0)
return false;
// TODO(riverriddle) We currently only eliminate non side-effecting
void CSE::simplifyBlock(DominanceInfo &domInfo, Block *bb) {
for (auto &i : *bb) {
- // If the operation is simplified, we don't process any held block lists.
+ // If the operation is simplified, we don't process any held regions.
if (simplifyOperation(&i))
continue;
// Simplify any held blocks.
- for (auto &blockList : i.getBlockLists())
- simplifyBlockList(domInfo, blockList);
+ for (auto ®ion : i.getRegions())
+ simplifyRegion(domInfo, region);
}
}
-void CSE::simplifyBlockList(DominanceInfo &domInfo, BlockList &blockList) {
- // If the block list is empty there is nothing to do.
- if (blockList.empty())
+void CSE::simplifyRegion(DominanceInfo &domInfo, Region ®ion) {
+ // If the region is empty there is nothing to do.
+ if (region.empty())
return;
- // If the block list only contains one block, then simplify it directly.
- if (std::next(blockList.begin()) == blockList.end()) {
+ // If the region only contains one block, then simplify it directly.
+ if (std::next(region.begin()) == region.end()) {
ScopedMapTy::ScopeTy scope(knownValues);
- simplifyBlock(domInfo, &blockList.front());
+ simplifyBlock(domInfo, ®ion.front());
return;
}
// http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120116/135228.html
std::deque<std::unique_ptr<CFGStackNode>> stack;
- // Process the nodes of the dom tree for this blocklist.
+ // Process the nodes of the dom tree for this region.
stack.emplace_back(std::make_unique<CFGStackNode>(
- knownValues, domInfo.getRootNode(&blockList)));
+ knownValues, domInfo.getRootNode(®ion)));
while (!stack.empty()) {
auto ¤tNode = stack.back();
}
void CSE::runOnFunction() {
- simplifyBlockList(getAnalysis<DominanceInfo>(),
- getFunction()->getBlockList());
+ simplifyRegion(getAnalysis<DominanceInfo>(), getFunction()->getBody());
// If no operations were erased, then we mark all analyses as preserved.
if (opsToErase.empty()) {
// Iterate over ops and convert them.
for (Instruction &inst : *block) {
- if (inst.getNumBlockLists() != 0) {
+ if (inst.getNumRegions() != 0) {
inst.emitError("unsupported region instruction");
return failure();
}
instToWalk->walk([&](Instruction *opInst) {
if (opInst->isa<AffineForOp>())
forOps.push_back(opInst->cast<AffineForOp>());
- else if (opInst->getNumBlockLists() != 0)
+ else if (opInst->getNumRegions() != 0)
hasNonForRegion = true;
else if (opInst->isa<LoadOp>())
loadOpInsts.push_back(opInst);
auto *memref = inst.cast<StoreOp>()->getMemRef();
memrefAccesses[memref].insert(node.id);
nodes.insert({node.id, node});
- } else if (inst.getNumBlockLists() != 0) {
+ } else if (inst.getNumRegions() != 0) {
// Return false if another region is found (not currently supported).
return false;
} else if (inst.getNumResults() > 0 && !inst.use_empty()) {
}
bool walkPostOrder(Instruction *opInst) {
bool hasInnerLoops = false;
- for (auto &blockList : opInst->getBlockLists())
- for (auto &block : blockList)
+ for (auto ®ion : opInst->getRegions())
+ for (auto &block : region)
hasInnerLoops |= walkPostOrder(block.begin(), block.end());
if (opInst->isa<AffineForOp>()) {
if (!hasInnerLoops)
// This is a linear time walk.
void walk(Instruction *inst) {
- for (auto &blockList : inst->getBlockLists())
- for (auto &block : blockList)
+ for (auto ®ion : inst->getRegions())
+ for (auto &block : region)
walk(block);
}
void walk(Block &block) {
"Should call the function specialized for VectorTransferReadOp");
assert(!opInst->isa<VectorTransferWriteOp>() &&
"Should call the function specialized for VectorTransferWriteOp");
- if (opInst->getNumBlockLists() != 0)
+ if (opInst->getNumRegions() != 0)
return nullptr;
bool fail = false;
if (inst->isa<AffineApplyOp>()) {
return false;
}
- if (inst->getNumBlockLists() != 0)
+ if (inst->getNumRegions() != 0)
return inst->emitError("NYI path Op with region");
if (auto write = inst->dyn_cast<VectorTransferWriteOp>()) {
opInst->erase();
return res;
}
- if (opInst->getNumBlockLists() != 0)
+ if (opInst->getNumRegions() != 0)
return nullptr;
auto types = map([state](Value *v) { return getVectorType(v, *state); },
OperationState newOp(b->getContext(), opInst->getLoc(),
opInst->getName().getStringRef(), operands, types,
opInst->getAttrs(), /*successors=*/{},
- /*numBlockLists=*/0, opInst->hasResizableOperandsList());
+ /*numRegions=*/0, opInst->hasResizableOperandsList());
return b->createOperation(newOp);
}
func @incomplete_for() {
for %i = 1 to 10 step 2
-} // expected-error {{expected '{' to begin block list}}
+} // expected-error {{expected '{' to begin a region}}
// -----
// CHECK-NEXT: "add"
%y = "add"(%c, %N) : (index, index) -> index
// CHECK-NEXT: } else {
- } { // The else block list.
+ } { // The else region.
// CHECK-NEXT: "add"
%z = "add"(%c, %c) : (index, index) -> index
}