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> ®ions) { 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