1//===-- ControlFlowInterfaces.td - ControlFlow Interfaces --*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a set of interfaces that can be used to define information
10// about control flow operations, e.g. branches.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_INTERFACES_CONTROLFLOWINTERFACES
15#define MLIR_INTERFACES_CONTROLFLOWINTERFACES
16
17include "mlir/IR/OpBase.td"
18
19//===----------------------------------------------------------------------===//
20// BranchOpInterface
21//===----------------------------------------------------------------------===//
22
23def BranchOpInterface : OpInterface<"BranchOpInterface"> {
24  let description = [{
25    This interface provides information for branching terminator operations,
26    i.e. terminator operations with successors.
27  }];
28  let methods = [
29    InterfaceMethod<[{
30        Returns a mutable range of operands that correspond to the arguments of
31        successor at the given index. Returns None if the operands to the
32        successor are non-materialized values, i.e. they are internal to the
33        operation.
34      }],
35      "Optional<MutableOperandRange>", "getMutableSuccessorOperands",
36      (ins "unsigned":$index)
37    >,
38    InterfaceMethod<[{
39        Returns a range of operands that correspond to the arguments of
40        successor at the given index. Returns None if the operands to the
41        successor are non-materialized values, i.e. they are internal to the
42        operation.
43      }],
44      "Optional<OperandRange>", "getSuccessorOperands",
45      (ins "unsigned":$index), [{}], [{
46        ConcreteOp *op = static_cast<ConcreteOp *>(this);
47        auto operands = op->getMutableSuccessorOperands(index);
48        return operands ? Optional<OperandRange>(*operands) : llvm::None;
49      }]
50    >,
51    InterfaceMethod<[{
52        Returns the `BlockArgument` corresponding to operand `operandIndex` in
53        some successor, or None if `operandIndex` isn't a successor operand
54        index.
55      }],
56      "Optional<BlockArgument>", "getSuccessorBlockArgument",
57      (ins "unsigned":$operandIndex), [{
58        Operation *opaqueOp = op;
59        for (unsigned i = 0, e = opaqueOp->getNumSuccessors(); i != e; ++i) {
60          if (Optional<BlockArgument> arg = detail::getBranchSuccessorArgument(
61                op.getSuccessorOperands(i), operandIndex,
62                opaqueOp->getSuccessor(i)))
63            return arg;
64        }
65        return llvm::None;
66      }]
67    >,
68    InterfaceMethod<[{
69        Returns the successor that would be chosen with the given constant
70        operands. Returns nullptr if a single successor could not be chosen.
71      }],
72      "Block *", "getSuccessorForOperands",
73      (ins "ArrayRef<Attribute>":$operands), [{}],
74      /*defaultImplementation=*/[{ return nullptr; }]
75    >
76  ];
77
78  let verify = [{
79    auto concreteOp = cast<ConcreteOpType>($_op);
80    for (unsigned i = 0, e = $_op->getNumSuccessors(); i != e; ++i) {
81      Optional<OperandRange> operands = concreteOp.getSuccessorOperands(i);
82      if (failed(detail::verifyBranchSuccessorOperands($_op, i, operands)))
83        return failure();
84    }
85    return success();
86  }];
87}
88
89//===----------------------------------------------------------------------===//
90// RegionBranchOpInterface
91//===----------------------------------------------------------------------===//
92
93def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
94  let description = [{
95    This interface provides information for region operations that contain
96    branching behavior between held regions, i.e. this interface allows for
97    expressing control flow information for region holding operations.
98  }];
99  let methods = [
100    InterfaceMethod<[{
101        Returns the operands of this operation used as the entry arguments when
102        entering the region at `index`, which was specified as a successor by
103        `getSuccessorRegions`. These operands should correspond 1-1 with the
104        successor inputs specified in `getSuccessorRegions`, and may corre
105      }],
106      "OperandRange", "getSuccessorEntryOperands",
107      (ins "unsigned":$index), [{}], /*defaultImplementation=*/[{
108        auto operandEnd = this->getOperation()->operand_end();
109        return OperandRange(operandEnd, operandEnd);
110      }]
111    >,
112    InterfaceMethod<[{
113        Returns the viable successors of a region at `index`, or the possible
114        successors when branching from the parent op if `index` is None. These
115        are the regions that may be selected during the flow of control. If
116        `index` is None, `operands` is a set of optional attributes that
117        either correspond to a constant value for each operand of this
118        operation, or null if that operand is not a constant. If `index` is
119        valid, `operands` corresponds to the exit values of the region at
120        `index`. Only a region, i.e. a valid `index`, may use the parent
121        operation as a successor. This method allows for describing which
122        regions may be executed when entering an operation, and which regions
123        are executed after having executed another region of the parent op. The
124        successor region must be non-empty.
125      }],
126      "void", "getSuccessorRegions",
127      (ins "Optional<unsigned>":$index, "ArrayRef<Attribute>":$operands,
128           "SmallVectorImpl<RegionSuccessor> &":$regions)
129    >
130  ];
131}
132
133//===----------------------------------------------------------------------===//
134// ControlFlow Traits
135//===----------------------------------------------------------------------===//
136
137// Op is "return-like".
138def ReturnLike : NativeOpTrait<"ReturnLike">;
139
140#endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES
141