llvm/mlir/include/mlir/IR/BlockSupport.h

//===- BlockSupport.h -------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines a number of support types for the Block class.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_BLOCKSUPPORT_H
#define MLIR_IR_BLOCKSUPPORT_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;

//===----------------------------------------------------------------------===//
// BlockOperand
//===----------------------------------------------------------------------===//

/// A block operand represents an operand that holds a reference to a Block,
/// e.g. for terminator operations.
class BlockOperand : public IROperand<BlockOperand, 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 &)> {};

//===----------------------------------------------------------------------===//
// Successors
//===----------------------------------------------------------------------===//

/// This class implements the successor iterators for Block.
class SuccessorRange final
    : public llvm::detail::indexed_accessor_range_base<
          SuccessorRange, BlockOperand *, Block *, Block *, Block *> {};

//===----------------------------------------------------------------------===//
// BlockRange
//===----------------------------------------------------------------------===//

/// This class provides an abstraction over the different types of ranges over
/// Blocks. In many cases, this prevents the need to explicitly materialize a
/// SmallVector/std::vector. This class should be used in places that are not
/// suitable for a more derived type (e.g. ArrayRef) or a template range
/// parameter.
class BlockRange final
    : public llvm::detail::indexed_accessor_range_base<
          BlockRange, llvm::PointerUnion<BlockOperand *, Block *const *>,
          Block *, Block *, Block *> {};

//===----------------------------------------------------------------------===//
// Operation Iterators
//===----------------------------------------------------------------------===//

namespace detail {
/// A utility iterator that filters out operations that are not 'OpT'.
template <typename OpT, typename IteratorT>
class op_filter_iterator
    : public llvm::filter_iterator<IteratorT, bool (*)(Operation &)> {};

/// This class provides iteration over the held operations of a block for a
/// specific operation type.
template <typename OpT, typename IteratorT>
class op_iterator
    : public llvm::mapped_iterator<op_filter_iterator<OpT, IteratorT>,
                                   OpT (*)(Operation &)> {};
} // namespace detail
} // namespace mlir

namespace llvm {

/// Provide support for hashing successor ranges.
template <>
struct DenseMapInfo<mlir::SuccessorRange> {};

//===----------------------------------------------------------------------===//
// 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 {};
} // namespace ilist_detail

template <>
struct ilist_traits<::mlir::Operation> {};

//===----------------------------------------------------------------------===//
// ilist_traits for Block
//===----------------------------------------------------------------------===//

template <>
struct ilist_traits<::mlir::Block> : public ilist_alloc_traits<::mlir::Block> {};

} // namespace llvm

#endif // MLIR_IR_BLOCKSUPPORT_H