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 cppNamespace = "::mlir";
29
30  let methods = [
31    InterfaceMethod<[{
32        Returns a mutable range of operands that correspond to the arguments of
33        successor at the given index. Returns None if the operands to the
34        successor are non-materialized values, i.e. they are internal to the
35        operation.
36      }],
37      "Optional<MutableOperandRange>", "getMutableSuccessorOperands",
38      (ins "unsigned":$index)
39    >,
40    InterfaceMethod<[{
41        Returns a range of operands that correspond to the arguments of
42        successor at the given index. Returns None if the operands to the
43        successor are non-materialized values, i.e. they are internal to the
44        operation.
45      }],
46      "Optional<OperandRange>", "getSuccessorOperands",
47      (ins "unsigned":$index), [{}], [{
48        ConcreteOp *op = static_cast<ConcreteOp *>(this);
49        auto operands = op->getMutableSuccessorOperands(index);
50        return operands ? Optional<OperandRange>(*operands) : llvm::None;
51      }]
52    >,
53    InterfaceMethod<[{
54        Returns the `BlockArgument` corresponding to operand `operandIndex` in
55        some successor, or None if `operandIndex` isn't a successor operand
56        index.
57      }],
58      "Optional<BlockArgument>", "getSuccessorBlockArgument",
59      (ins "unsigned":$operandIndex), [{
60        Operation *opaqueOp = $_op;
61        for (unsigned i = 0, e = opaqueOp->getNumSuccessors(); i != e; ++i) {
62          if (Optional<BlockArgument> arg = detail::getBranchSuccessorArgument(
63                $_op.getSuccessorOperands(i), operandIndex,
64                opaqueOp->getSuccessor(i)))
65            return arg;
66        }
67        return llvm::None;
68      }]
69    >,
70    InterfaceMethod<[{
71        Returns the successor that would be chosen with the given constant
72        operands. Returns nullptr if a single successor could not be chosen.
73      }],
74      "Block *", "getSuccessorForOperands",
75      (ins "ArrayRef<Attribute>":$operands), [{}],
76      /*defaultImplementation=*/[{ return nullptr; }]
77    >
78  ];
79
80  let verify = [{
81    auto concreteOp = cast<ConcreteOpType>($_op);
82    for (unsigned i = 0, e = $_op->getNumSuccessors(); i != e; ++i) {
83      Optional<OperandRange> operands = concreteOp.getSuccessorOperands(i);
84      if (failed(detail::verifyBranchSuccessorOperands($_op, i, operands)))
85        return failure();
86    }
87    return success();
88  }];
89}
90
91//===----------------------------------------------------------------------===//
92// RegionBranchOpInterface
93//===----------------------------------------------------------------------===//
94
95def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
96  let description = [{
97    This interface provides information for region operations that contain
98    branching behavior between held regions, i.e. this interface allows for
99    expressing control flow information for region holding operations.
100  }];
101  let cppNamespace = "::mlir";
102
103  let methods = [
104    InterfaceMethod<[{
105        Returns the operands of this operation used as the entry arguments when
106        entering the region at `index`, which was specified as a successor of this
107        operation by `getSuccessorRegions`. These operands should correspond 1-1
108        with the successor inputs specified in `getSuccessorRegions`.
109      }],
110      "OperandRange", "getSuccessorEntryOperands",
111      (ins "unsigned":$index), [{}], /*defaultImplementation=*/[{
112        auto operandEnd = this->getOperation()->operand_end();
113        return OperandRange(operandEnd, operandEnd);
114      }]
115    >,
116    InterfaceMethod<[{
117        Returns the viable successors of a region at `index`, or the possible
118        successors when branching from the parent op if `index` is None. These
119        are the regions that may be selected during the flow of control. If
120        `index` is None, `operands` is a set of optional attributes that
121        either correspond to a constant value for each operand of this
122        operation, or null if that operand is not a constant. If `index` is
123        valid, `operands` corresponds to the exit values of the region at
124        `index`. Only a region, i.e. a valid `index`, may use the parent
125        operation as a successor. This method allows for describing which
126        regions may be executed when entering an operation, and which regions
127        are executed after having executed another region of the parent op. The
128        successor region must be non-empty.
129      }],
130      "void", "getSuccessorRegions",
131      (ins "Optional<unsigned>":$index, "ArrayRef<Attribute>":$operands,
132           "SmallVectorImpl<RegionSuccessor> &":$regions)
133    >,
134    InterfaceMethod<[{
135        Populates countPerRegion with the number of times this operation will
136        invoke the attached regions (assuming the regions yield normally, i.e.
137        do not abort or invoke an infinite loop). If the number of region
138        invocations is not known statically it will set the number of
139        invocations to `kUnknownNumRegionInvocations`.
140
141        `operands` is a set of optional attributes that either correspond to a
142        constant values for each operand of this operation, or null if that
143        operand is not a constant.
144      }],
145      "void", "getNumRegionInvocations",
146      (ins "ArrayRef<Attribute>":$operands,
147           "SmallVectorImpl<int64_t> &":$countPerRegion), [{}],
148      /*defaultImplementation=*/[{
149        unsigned numRegions = this->getOperation()->getNumRegions();
150        assert(countPerRegion.empty());
151        countPerRegion.resize(numRegions, kUnknownNumRegionInvocations);
152      }]
153    >
154  ];
155
156  let verify = [{
157    static_assert(!ConcreteOpType::template hasTrait<OpTrait::ZeroRegion>(),
158                  "expected operation to have non-zero regions");
159    return success();
160  }];
161
162  let extraClassDeclaration = [{
163    /// Convenience helper in case none of the operands is known.
164    void getSuccessorRegions(Optional<unsigned> index,
165                             SmallVectorImpl<RegionSuccessor> &regions) {
166       SmallVector<Attribute, 2> nullAttrs(getOperation()->getNumOperands());
167       getSuccessorRegions(index, nullAttrs, regions);
168    }
169
170    /// Verify types along control flow edges described by this interface.
171    static LogicalResult verifyTypes(Operation *op) {
172      return detail::verifyTypesAlongControlFlowEdges(op);
173    }
174  }];
175}
176
177//===----------------------------------------------------------------------===//
178// ControlFlow Traits
179//===----------------------------------------------------------------------===//
180
181// Op is "return-like".
182def ReturnLike : NativeOpTrait<"ReturnLike">;
183
184#endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES
185