//===- ControlFlowInterfaces.h - ControlFlow Interfaces ---------*- 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 contains the definitions of the branch interfaces defined in // `ControlFlowInterfaces.td`. // //===----------------------------------------------------------------------===// #ifndef MLIR_INTERFACES_CONTROLFLOWINTERFACES_H #define MLIR_INTERFACES_CONTROLFLOWINTERFACES_H #include "mlir/IR/OpDefinition.h" namespace mlir { class BranchOpInterface; class RegionBranchOpInterface; /// This class models how operands are forwarded to block arguments in control /// flow. It consists of a number, denoting how many of the successors block /// arguments are produced by the operation, followed by a range of operands /// that are forwarded. The produced operands are passed to the first few /// block arguments of the successor, followed by the forwarded operands. /// It is unsupported to pass them in a different order. /// /// An example operation with both of these concepts would be a branch-on-error /// operation, that internally produces an error object on the error path: /// /// invoke %function(%0) /// label ^success ^error(%1 : i32) /// /// ^error(%e: !error, %arg0 : i32): /// ... /// /// This operation would return an instance of SuccessorOperands with a produced /// operand count of 1 (mapped to %e in the successor) and a forwarded /// operands range consisting of %1 in the example above (mapped to %arg0 in the /// successor). class SuccessorOperands { … }; //===----------------------------------------------------------------------===// // BranchOpInterface //===----------------------------------------------------------------------===// namespace detail { /// Return the `BlockArgument` corresponding to operand `operandIndex` in some /// successor if `operandIndex` is within the range of `operands`, or /// std::nullopt if `operandIndex` isn't a successor operand index. std::optional<BlockArgument> getBranchSuccessorArgument(const SuccessorOperands &operands, unsigned operandIndex, Block *successor); /// Verify that the given operands match those of the given successor block. LogicalResult verifyBranchSuccessorOperands(Operation *op, unsigned succNo, const SuccessorOperands &operands); } // namespace detail //===----------------------------------------------------------------------===// // RegionBranchOpInterface //===----------------------------------------------------------------------===// namespace detail { /// Verify that types match along control flow edges described the given op. LogicalResult verifyTypesAlongControlFlowEdges(Operation *op); } // namespace detail /// This class represents a successor of a region. A region successor can either /// be another region, or the parent operation. If the successor is a region, /// this class represents the destination region, as well as a set of arguments /// from that region that will be populated when control flows into the region. /// If the successor is the parent operation, this class represents an optional /// set of results that will be populated when control returns to the parent /// operation. /// /// This interface assumes that the values from the current region that are used /// to populate the successor inputs are the operands of the return-like /// terminator operations in the blocks within this region. class RegionSuccessor { … }; /// This class represents a point being branched from in the methods of the /// `RegionBranchOpInterface`. /// One can branch from one of two kinds of places: /// * The parent operation (aka the `RegionBranchOpInterface` implementation) /// * A region within the parent operation. class RegionBranchPoint { … }; inline bool operator!=(RegionBranchPoint lhs, RegionBranchPoint rhs) { … } /// This class represents upper and lower bounds on the number of times a region /// of a `RegionBranchOpInterface` can be invoked. The lower bound is at least /// zero, but the upper bound may not be known. class InvocationBounds { … }; /// Return `true` if `a` and `b` are in mutually exclusive regions as per /// RegionBranchOpInterface. bool insideMutuallyExclusiveRegions(Operation *a, Operation *b); /// Return the first enclosing region of the given op that may be executed /// repetitively as per RegionBranchOpInterface or `nullptr` if no such region /// exists. Region *getEnclosingRepetitiveRegion(Operation *op); /// Return the first enclosing region of the given Value that may be executed /// repetitively as per RegionBranchOpInterface or `nullptr` if no such region /// exists. Region *getEnclosingRepetitiveRegion(Value value); //===----------------------------------------------------------------------===// // ControlFlow Traits //===----------------------------------------------------------------------===// namespace OpTrait { /// This trait indicates that a terminator operation is "return-like". This /// means that it exits its current region and forwards its operands as "exit" /// values to the parent region. Operations with this trait are not permitted to /// contain successors or produce results. template <typename ConcreteType> struct ReturnLike : public TraitBase<ConcreteType, ReturnLike> { … }; } // namespace OpTrait } // namespace mlir //===----------------------------------------------------------------------===// // ControlFlow Interfaces //===----------------------------------------------------------------------===// /// Include the generated interface declarations. #include "mlir/Interfaces/ControlFlowInterfaces.h.inc" #endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES_H