forked from OSchip/llvm-project
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:
parent
7be6a40ab9
commit
3f9744a6b7
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue