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
This commit is contained in:
River Riddle 2019-12-09 15:24:10 -08:00 committed by A. Unique TensorFlower
parent 7be6a40ab9
commit 3f9744a6b7
3 changed files with 177 additions and 157 deletions

View File

@ -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<mlir::Operation>::type;
using pointer = typename OptionsT::pointer;
using const_pointer = typename OptionsT::const_pointer;
using node_type = ilist_node_impl<OptionsT>;
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<Operation>::iterator;
static void deleteNode(Operation *op);
void addNodeToList(Operation *op);
void removeNodeFromList(Operation *op);
void transferNodesFromList(ilist_traits<Operation> &otherList,
op_iterator first, op_iterator last);
private:
mlir::Block *getContainingBlock();
};
} // end namespace llvm
namespace mlir {
using BlockOperand = IROperandImpl<Block>;
class PredecessorIterator;
class SuccessorIterator;
/// `Block` represents an ordered list of `Operation`s.
class Block : public IRObjectWithUseList,
public llvm::ilist_node_with_parent<Block, Region> {
@ -272,9 +222,13 @@ public:
// Predecessor iteration.
using pred_iterator = PredecessorIterator;
pred_iterator pred_begin();
pred_iterator pred_end();
llvm::iterator_range<pred_iterator> getPredecessors();
pred_iterator pred_begin() {
return pred_iterator((BlockOperand *)getFirstUse());
}
pred_iterator pred_end() { return pred_iterator(nullptr); }
llvm::iterator_range<pred_iterator> 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<succ_iterator> 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<Block>;
};
} // 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<Block> &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<ValueUseIterator<BlockOperand>,
Block *(*)(BlockOperand &)> {
static Block *unwrap(BlockOperand &value);
public:
using reference = Block *;
/// Initializes the operand type iterator to the specified operand iterator.
PredecessorIterator(ValueUseIterator<BlockOperand> it)
: llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
Block *(*)(BlockOperand &)>(it, &unwrap) {}
explicit PredecessorIterator(BlockOperand *operand)
: PredecessorIterator(ValueUseIterator<BlockOperand>(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<pred_iterator> {
return {pred_begin(), pred_end()};
}
//===----------------------------------------------------------------------===//
// Successors
//===----------------------------------------------------------------------===//
/// This template implements the successor iterators for Block.
class SuccessorIterator final
: public indexed_accessor_iterator<SuccessorIterator, Block *, Block *,
Block *, Block *> {
public:
/// Initializes the result iterator to the specified index.
SuccessorIterator(Block *object, unsigned index)
: indexed_accessor_iterator<SuccessorIterator, Block *, Block *, Block *,
Block *>(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<succ_iterator> {
return {succ_begin(), succ_end()};
}
} // end namespace mlir
#endif // MLIR_IR_BLOCK_H

View File

@ -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<Block>;
//===----------------------------------------------------------------------===//
// 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<ValueUseIterator<BlockOperand>,
Block *(*)(BlockOperand &)> {
static Block *unwrap(BlockOperand &value);
public:
using reference = Block *;
/// Initializes the operand type iterator to the specified operand iterator.
PredecessorIterator(ValueUseIterator<BlockOperand> it)
: llvm::mapped_iterator<ValueUseIterator<BlockOperand>,
Block *(*)(BlockOperand &)>(it, &unwrap) {}
explicit PredecessorIterator(BlockOperand *operand)
: PredecessorIterator(ValueUseIterator<BlockOperand>(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<SuccessorRange, BlockOperand *,
Block *, Block *, Block *> {
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<SuccessorRange, BlockOperand *,
Block *, Block *, Block *>;
};
} // 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<mlir::Operation>::type;
using pointer = typename OptionsT::pointer;
using const_pointer = typename OptionsT::const_pointer;
using node_type = ilist_node_impl<OptionsT>;
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<Operation>::iterator;
static void deleteNode(Operation *op);
void addNodeToList(Operation *op);
void removeNodeFromList(Operation *op);
void transferNodesFromList(ilist_traits<Operation> &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<Block> &otherList,
block_iterator first, block_iterator last);
private:
mlir::Region *getParentRegion();
};
} // end namespace llvm
#endif // MLIR_IR_BLOCK_SUPPORT_H

View File

@ -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();
}