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 set of values that correspond to the arguments to the
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<OperandRange>", "getSuccessorOperands", (ins "unsigned":$index)
36    >,
37    InterfaceMethod<[{
38        Return true if this operation can erase an operand to a successor block.
39      }],
40      "bool", "canEraseSuccessorOperand"
41    >,
42    InterfaceMethod<[{
43        Erase the operand at `operandIndex` from the `index`-th successor. This
44        should only be called if `canEraseSuccessorOperand` returns true.
45      }],
46      "void", "eraseSuccessorOperand",
47      (ins "unsigned":$index, "unsigned":$operandIndex), [{}],
48      /*defaultImplementation=*/[{
49        ConcreteOp *op = static_cast<ConcreteOp *>(this);
50        Optional<OperandRange> operands = op->getSuccessorOperands(index);
51        assert(operands && "unable to query operands for successor");
52        detail::eraseBranchSuccessorOperand(*operands, operandIndex, *op);
53      }]
54    >,
55    InterfaceMethod<[{
56        Returns the `BlockArgument` corresponding to operand `operandIndex` in
57        some successor, or None if `operandIndex` isn't a successor operand
58        index.
59      }],
60      "Optional<BlockArgument>", "getSuccessorBlockArgument",
61      (ins "unsigned":$operandIndex), [{
62        Operation *opaqueOp = op;
63        for (unsigned i = 0, e = opaqueOp->getNumSuccessors(); i != e; ++i) {
64          if (Optional<BlockArgument> arg = detail::getBranchSuccessorArgument(
65                op.getSuccessorOperands(i), operandIndex,
66                opaqueOp->getSuccessor(i)))
67            return arg;
68        }
69        return llvm::None;
70      }]
71    >
72  ];
73
74  let verify = [{
75    auto concreteOp = cast<ConcreteOpType>($_op);
76    for (unsigned i = 0, e = $_op->getNumSuccessors(); i != e; ++i) {
77      Optional<OperandRange> operands = concreteOp.getSuccessorOperands(i);
78      if (failed(detail::verifyBranchSuccessorOperands($_op, i, operands)))
79        return failure();
80    }
81    return success();
82  }];
83}
84
85#endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES
86