From 3f9744a6b744b9213b0e34f4f3433db8276780f9 Mon Sep 17 00:00:00 2001 From: River Riddle Date: Mon, 9 Dec 2019 15:24:10 -0800 Subject: [PATCH] Refactor the Block support classes. Each of the support classes for Block are now moved into a new header BlockSupport.h. The successor iterator class is also reimplemented as an indexed_accessor_range. This makes the class more efficient, and expands on its available functionality. PiperOrigin-RevId: 284646792 --- mlir/include/mlir/IR/Block.h | 169 +++--------------------------------- mlir/include/mlir/IR/BlockSupport.h | 155 +++++++++++++++++++++++++++++++++ mlir/lib/IR/Block.cpp | 10 +++ 3 files changed, 177 insertions(+), 157 deletions(-) create mode 100644 mlir/include/mlir/IR/BlockSupport.h diff --git a/mlir/include/mlir/IR/Block.h b/mlir/include/mlir/IR/Block.h index 532352e..a36ecdd 100644 --- a/mlir/include/mlir/IR/Block.h +++ b/mlir/include/mlir/IR/Block.h @@ -22,60 +22,10 @@ #ifndef MLIR_IR_BLOCK_H #define MLIR_IR_BLOCK_H -#include "mlir/IR/Value.h" +#include "mlir/IR/BlockSupport.h" #include "mlir/IR/Visitors.h" -#include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" - -//===----------------------------------------------------------------------===// -// ilist_traits for Operation -//===----------------------------------------------------------------------===// - -namespace llvm { -namespace ilist_detail { -// Explicitly define the node access for the operation list so that we can -// break the dependence on the Operation class in this header. This allows for -// operations to have trailing Regions without a circular include -// dependence. -template <> -struct SpecificNodeAccess< - typename compute_node_options<::mlir::Operation>::type> : NodeAccess { -protected: - using OptionsT = typename compute_node_options::type; - using pointer = typename OptionsT::pointer; - using const_pointer = typename OptionsT::const_pointer; - using node_type = ilist_node_impl; - - static node_type *getNodePtr(pointer N); - static const node_type *getNodePtr(const_pointer N); - - static pointer getValuePtr(node_type *N); - static const_pointer getValuePtr(const node_type *N); -}; -} // end namespace ilist_detail - -template <> struct ilist_traits<::mlir::Operation> { - using Operation = ::mlir::Operation; - using op_iterator = simple_ilist::iterator; - - static void deleteNode(Operation *op); - void addNodeToList(Operation *op); - void removeNodeFromList(Operation *op); - void transferNodesFromList(ilist_traits &otherList, - op_iterator first, op_iterator last); - -private: - mlir::Block *getContainingBlock(); -}; -} // end namespace llvm namespace mlir { -using BlockOperand = IROperandImpl; - -class PredecessorIterator; -class SuccessorIterator; - /// `Block` represents an ordered list of `Operation`s. class Block : public IRObjectWithUseList, public llvm::ilist_node_with_parent { @@ -272,9 +222,13 @@ public: // Predecessor iteration. using pred_iterator = PredecessorIterator; - pred_iterator pred_begin(); - pred_iterator pred_end(); - llvm::iterator_range getPredecessors(); + pred_iterator pred_begin() { + return pred_iterator((BlockOperand *)getFirstUse()); + } + pred_iterator pred_end() { return pred_iterator(nullptr); } + llvm::iterator_range getPredecessors() { + return {pred_begin(), pred_end()}; + } /// Return true if this block has no predecessors. bool hasNoPredecessors(); @@ -292,10 +246,10 @@ public: Block *getSuccessor(unsigned i); // Successor iteration. - using succ_iterator = SuccessorIterator; - succ_iterator succ_begin(); - succ_iterator succ_end(); - llvm::iterator_range getSuccessors(); + using succ_iterator = SuccessorRange::iterator; + succ_iterator succ_begin() { return getSuccessors().begin(); } + succ_iterator succ_end() { return getSuccessors().end(); } + SuccessorRange getSuccessors() { return SuccessorRange(this); } //===--------------------------------------------------------------------===// // Operation Walkers @@ -381,105 +335,6 @@ private: friend struct llvm::ilist_traits; }; - -} // end namespace mlir - -//===----------------------------------------------------------------------===// -// ilist_traits for Block -//===----------------------------------------------------------------------===// - -namespace llvm { - -template <> -struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> { - using Block = ::mlir::Block; - using block_iterator = simple_ilist<::mlir::Block>::iterator; - - void addNodeToList(Block *block); - void removeNodeFromList(Block *block); - void transferNodesFromList(ilist_traits &otherList, - block_iterator first, block_iterator last); - -private: - mlir::Region *getParentRegion(); -}; -} // end namespace llvm - -namespace mlir { -//===----------------------------------------------------------------------===// -// Predecessors -//===----------------------------------------------------------------------===// - -/// Implement a predecessor iterator for blocks. This works by walking the use -/// lists of the blocks. The entries on this list are the BlockOperands that -/// are embedded into terminator operations. From the operand, we can get the -/// terminator that contains it, and its parent block is the predecessor. -class PredecessorIterator final - : public llvm::mapped_iterator, - Block *(*)(BlockOperand &)> { - static Block *unwrap(BlockOperand &value); - -public: - using reference = Block *; - - /// Initializes the operand type iterator to the specified operand iterator. - PredecessorIterator(ValueUseIterator it) - : llvm::mapped_iterator, - Block *(*)(BlockOperand &)>(it, &unwrap) {} - explicit PredecessorIterator(BlockOperand *operand) - : PredecessorIterator(ValueUseIterator(operand)) {} - - /// Get the successor number in the predecessor terminator. - unsigned getSuccessorIndex() const; -}; - -inline auto Block::pred_begin() -> pred_iterator { - return pred_iterator((BlockOperand *)getFirstUse()); -} - -inline auto Block::pred_end() -> pred_iterator { - return pred_iterator(nullptr); -} - -inline auto Block::getPredecessors() -> llvm::iterator_range { - return {pred_begin(), pred_end()}; -} - -//===----------------------------------------------------------------------===// -// Successors -//===----------------------------------------------------------------------===// - -/// This template implements the successor iterators for Block. -class SuccessorIterator final - : public indexed_accessor_iterator { -public: - /// Initializes the result iterator to the specified index. - SuccessorIterator(Block *object, unsigned index) - : indexed_accessor_iterator(object, index) {} - - SuccessorIterator(const SuccessorIterator &other) - : SuccessorIterator(other.base, other.index) {} - - Block *operator*() const { return this->base->getSuccessor(this->index); } - - /// Get the successor number in the terminator. - unsigned getSuccessorIndex() const { return this->index; } -}; - -inline auto Block::succ_begin() -> succ_iterator { - return succ_iterator(this, 0); -} - -inline auto Block::succ_end() -> succ_iterator { - return succ_iterator(this, getNumSuccessors()); -} - -inline auto Block::getSuccessors() -> llvm::iterator_range { - return {succ_begin(), succ_end()}; -} - } // end namespace mlir #endif // MLIR_IR_BLOCK_H diff --git a/mlir/include/mlir/IR/BlockSupport.h b/mlir/include/mlir/IR/BlockSupport.h new file mode 100644 index 0000000..83fbee3 --- /dev/null +++ b/mlir/include/mlir/IR/BlockSupport.h @@ -0,0 +1,155 @@ +//===- BlockSupport.h -------------------------------------------*- C++ -*-===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= +// +// This file defines a number of support types for the Block class. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_IR_BLOCK_SUPPORT_H +#define MLIR_IR_BLOCK_SUPPORT_H + +#include "mlir/IR/Value.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" + +namespace mlir { +class Block; + +using BlockOperand = IROperandImpl; + +//===----------------------------------------------------------------------===// +// Predecessors +//===----------------------------------------------------------------------===// + +/// Implement a predecessor iterator for blocks. This works by walking the use +/// lists of the blocks. The entries on this list are the BlockOperands that +/// are embedded into terminator operations. From the operand, we can get the +/// terminator that contains it, and its parent block is the predecessor. +class PredecessorIterator final + : public llvm::mapped_iterator, + Block *(*)(BlockOperand &)> { + static Block *unwrap(BlockOperand &value); + +public: + using reference = Block *; + + /// Initializes the operand type iterator to the specified operand iterator. + PredecessorIterator(ValueUseIterator it) + : llvm::mapped_iterator, + Block *(*)(BlockOperand &)>(it, &unwrap) {} + explicit PredecessorIterator(BlockOperand *operand) + : PredecessorIterator(ValueUseIterator(operand)) {} + + /// Get the successor number in the predecessor terminator. + unsigned getSuccessorIndex() const; +}; + +//===----------------------------------------------------------------------===// +// Successors +//===----------------------------------------------------------------------===// + +/// This class implements the successor iterators for Block. +class SuccessorRange final + : public detail::indexed_accessor_range_base { +public: + using detail::indexed_accessor_range_base< + SuccessorRange, BlockOperand *, Block *, Block *, + Block *>::indexed_accessor_range_base; + SuccessorRange(Block *block); + +private: + /// See `detail::indexed_accessor_range_base` for details. + static BlockOperand *offset_object(BlockOperand *object, ptrdiff_t index) { + return object + index; + } + /// See `detail::indexed_accessor_range_base` for details. + static Block *dereference_iterator(BlockOperand *object, ptrdiff_t index) { + return object[index].get(); + } + + /// Allow access to `offset_object` and `dereference_iterator`. + friend detail::indexed_accessor_range_base; +}; + +} // end namespace mlir + +namespace llvm { + +//===----------------------------------------------------------------------===// +// ilist_traits for Operation +//===----------------------------------------------------------------------===// + +namespace ilist_detail { +// Explicitly define the node access for the operation list so that we can +// break the dependence on the Operation class in this header. This allows for +// operations to have trailing Regions without a circular include +// dependence. +template <> +struct SpecificNodeAccess< + typename compute_node_options<::mlir::Operation>::type> : NodeAccess { +protected: + using OptionsT = typename compute_node_options::type; + using pointer = typename OptionsT::pointer; + using const_pointer = typename OptionsT::const_pointer; + using node_type = ilist_node_impl; + + static node_type *getNodePtr(pointer N); + static const node_type *getNodePtr(const_pointer N); + + static pointer getValuePtr(node_type *N); + static const_pointer getValuePtr(const node_type *N); +}; +} // end namespace ilist_detail + +template <> struct ilist_traits<::mlir::Operation> { + using Operation = ::mlir::Operation; + using op_iterator = simple_ilist::iterator; + + static void deleteNode(Operation *op); + void addNodeToList(Operation *op); + void removeNodeFromList(Operation *op); + void transferNodesFromList(ilist_traits &otherList, + op_iterator first, op_iterator last); + +private: + mlir::Block *getContainingBlock(); +}; + +//===----------------------------------------------------------------------===// +// ilist_traits for Block +//===----------------------------------------------------------------------===// + +template <> +struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> { + using Block = ::mlir::Block; + using block_iterator = simple_ilist<::mlir::Block>::iterator; + + void addNodeToList(Block *block); + void removeNodeFromList(Block *block); + void transferNodesFromList(ilist_traits &otherList, + block_iterator first, block_iterator last); + +private: + mlir::Region *getParentRegion(); +}; + +} // end namespace llvm + +#endif // MLIR_IR_BLOCK_SUPPORT_H diff --git a/mlir/lib/IR/Block.cpp b/mlir/lib/IR/Block.cpp index ad68a36..ea92422 100644 --- a/mlir/lib/IR/Block.cpp +++ b/mlir/lib/IR/Block.cpp @@ -257,3 +257,13 @@ Block *PredecessorIterator::unwrap(BlockOperand &value) { unsigned PredecessorIterator::getSuccessorIndex() const { return I->getOperandNumber(); } + +//===----------------------------------------------------------------------===// +// Successors +//===----------------------------------------------------------------------===// + +SuccessorRange::SuccessorRange(Block *block) : SuccessorRange(nullptr, 0) { + if (Operation *term = block->getTerminator()) + if ((count = term->getNumSuccessors())) + base = term->getBlockOperands().data(); +} -- 2.7.4