@@ -117,27 +117,58 @@ def BranchOpInterface : OpInterface<"BranchOpInterface"> {
117117
118118def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
119119 let description = [{
120- This interface provides information for region operations that contain
121- branching behavior between held regions, i .e. this interface allows for
120+ This interface provides information for region operations that exhibit
121+ branching behavior between held regions. I .e., this interface allows for
122122 expressing control flow information for region holding operations.
123123
124- This interface is meant to model well-defined cases of control-flow of
124+ This interface is meant to model well-defined cases of control-flow and
125125 value propagation, where what occurs along control-flow edges is assumed to
126- be side-effect free. For example, corresponding successor operands and
127- successor block arguments may have different types. In such cases,
128- `areTypesCompatible` can be implemented to compare types along control-flow
129- edges. By default, type equality is used.
126+ be side-effect free.
127+
128+ A "region branch point" indicates a point from which a branch originates. It
129+ can indicate either a region of this op or `RegionBranchPoint::parent()`. In
130+ the latter case, the branch originates from outside of the op, i.e., when
131+ first executing this op.
132+
133+ A "region successor" indicates the target of a branch. It can indicate
134+ either a region of this op or this op. In the former case, the region
135+ successor is a region pointer and a range of block arguments to which the
136+ "successor operands" are forwarded to. In the latter case, the control flow
137+ leaves this op and the region successor is a range of results of this op to
138+ which the successor operands are forwarded to.
139+
140+ By default, successor operands and successor block arguments/successor
141+ results must have the same type. `areTypesCompatible` can be implemented to
142+ allow non-equal types.
143+
144+ Example:
145+
146+ ```
147+ %r = scf.for %iv = %lb to %ub step %step iter_args(%a = %b)
148+ -> tensor<5xf32> {
149+ ...
150+ scf.yield %c : tensor<5xf32>
151+ }
152+ ```
153+
154+ `scf.for` has one region. The region has two region successors: the region
155+ itself and the `scf.for` op. %b is an entry successor operand. %c is a
156+ successor operand. %a is a successor block argument. %r is a successor
157+ result.
130158 }];
131159 let cppNamespace = "::mlir";
132160
133161 let methods = [
134162 InterfaceMethod<[{
135- Returns the operands of this operation used as the entry arguments when
136- branching from `point`, which was specified as a successor of
137- this operation by `getEntrySuccessorRegions`, or the operands forwarded
138- to the operation's results when it branches back to itself. These operands
139- should correspond 1-1 with the successor inputs specified in
140- `getEntrySuccessorRegions`.
163+ Returns the operands of this operation that are forwarded to the region
164+ successor's block arguments or this operation's results when branching
165+ to `point`. `point` is guaranteed to be among the successors that are
166+ returned by `getEntrySuccessorRegions`/`getSuccessorRegions(parent())`.
167+
168+ Example: In the above example, this method returns the operand %b of the
169+ `scf.for` op, regardless of the value of `point`. I.e., this op always
170+ forwards the same operands, regardless of whether the loop has 0 or more
171+ iterations.
141172 }],
142173 "::mlir::OperandRange", "getEntrySuccessorOperands",
143174 (ins "::mlir::RegionBranchPoint":$point), [{}],
@@ -147,32 +178,47 @@ def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
147178 }]
148179 >,
149180 InterfaceMethod<[{
150- Returns the viable region successors that are branched to when first
151- executing the op.
181+ Returns the potential region successors when first executing the op.
182+
152183 Unlike `getSuccessorRegions`, this method also passes along the
153- constant operands of this op. Based on these, different region
154- successors can be determined.
155- `operands` contains an entry for every operand of the implementing
156- op with a null attribute if the operand has no constant value or
157- the corresponding attribute if it is a constant.
184+ constant operands of this op. Based on these, the implementation may
185+ filter out certain successors. By default, simply dispatches to
186+ `getSuccessorRegions`. `operands` contains an entry for every
187+ operand of this op, with a null attribute if the operand has no constant
188+ value.
189+
190+ Note: The control flow does not necessarily have to enter any region of
191+ this op.
158192
159- By default, simply dispatches to `getSuccessorRegions`.
193+ Example: In the above example, this method may return two region
194+ region successors: the single region of the `scf.for` op and the
195+ `scf.for` operation (that implements this interface). If %lb, %ub, %step
196+ are constants and it can be determined the loop does not have any
197+ iterations, this method may choose to return only this operation.
198+ Similarly, if it can be determined that the loop has at least one
199+ iteration, this method may choose to return only the region of the loop.
160200 }],
161201 "void", "getEntrySuccessorRegions",
162202 (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
163- "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions),
164- [{}], [{
203+ "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions), [{}],
204+ /*defaultImplementation=*/ [{
165205 $_op.getSuccessorRegions(mlir::RegionBranchPoint::parent(), regions);
166206 }]
167207 >,
168208 InterfaceMethod<[{
169- Returns the viable successors of `point`. These are the regions that may
170- be selected during the flow of control. The parent operation, may
171- specify itself as successor, which indicates that the control flow may
172- not enter any region at all. This method allows for describing which
173- regions may be executed when entering an operation, and which regions
174- are executed after having executed another region of the parent op. The
175- successor region must be non-empty.
209+ Returns the potential region successors when branching from `point`.
210+ These are the regions that may be selected during the flow of control.
211+
212+ When `point = RegionBranchPoint::parent()`, this method returns the
213+ region successors when entering the operation. Otherwise, this method
214+ returns the successor regions when branching from the region indicated
215+ by `point`.
216+
217+ Example: In the above example, this method returns the region of the
218+ `scf.for` and this operation for either region branch point (`parent`
219+ and the region of the `scf.for`). An implementation may choose to filter
220+ out region successors when it is statically known (e.g., by examining
221+ the operands of this op) that those successors are not branched to.
176222 }],
177223 "void", "getSuccessorRegions",
178224 (ins "::mlir::RegionBranchPoint":$point,
@@ -183,12 +229,12 @@ def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
183229 times this operation will invoke the attached regions (assuming the
184230 regions yield normally, i.e. do not abort or invoke an infinite loop).
185231 The minimum number of invocations is at least 0. If the maximum number
186- of invocations cannot be statically determined, then it will not have a
187- value (i.e., it is set to `std::nullopt`) .
232+ of invocations cannot be statically determined, then it will be set to
233+ `InvocationBounds::getUnknown()` .
188234
189- `operands` is a set of optional attributes that either correspond to
190- constant values for each operand of this operation or null if that
191- operand is not a constant.
235+ This method also passes along the constant operands of this op.
236+ `operands` contains an entry for every operand of this op, with a null
237+ attribute if the operand has no constant value .
192238
193239 This method may be called speculatively on operations where the provided
194240 operands are not necessarily the same as the operation's current
@@ -199,16 +245,18 @@ def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
199245 (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
200246 "::llvm::SmallVectorImpl<::mlir::InvocationBounds> &"
201247 :$invocationBounds), [{}],
202- [{ invocationBounds.append($_op->getNumRegions(),
203- ::mlir::InvocationBounds::getUnknown()); }]
248+ /*defaultImplementation=*/[{
249+ invocationBounds.append($_op->getNumRegions(),
250+ ::mlir::InvocationBounds::getUnknown());
251+ }]
204252 >,
205253 InterfaceMethod<[{
206254 This method is called to compare types along control-flow edges. By
207255 default, the types are checked as equal.
208256 }],
209257 "bool", "areTypesCompatible",
210258 (ins "::mlir::Type":$lhs, "::mlir::Type":$rhs), [{}],
211- [{ return lhs == rhs; }]
259+ /*defaultImplementation=*/ [{ return lhs == rhs; }]
212260 >,
213261 ];
214262
@@ -235,34 +283,34 @@ def RegionBranchTerminatorOpInterface :
235283 OpInterface<"RegionBranchTerminatorOpInterface"> {
236284 let description = [{
237285 This interface provides information for branching terminator operations
238- in the presence of a parent RegionBranchOpInterface implementation. It
286+ in the presence of a parent ` RegionBranchOpInterface` implementation. It
239287 specifies which operands are passed to which successor region.
240288 }];
241289 let cppNamespace = "::mlir";
242290
243291 let methods = [
244292 InterfaceMethod<[{
245293 Returns a mutable range of operands that are semantically "returned" by
246- passing them to the region successor given by `point`.
294+ passing them to the region successor indicated by `point`.
247295 }],
248296 "::mlir::MutableOperandRange", "getMutableSuccessorOperands",
249297 (ins "::mlir::RegionBranchPoint":$point)
250298 >,
251299 InterfaceMethod<[{
252- Returns the viable region successors that are branched to after this
300+ Returns the potential region successors that are branched to after this
253301 terminator based on the given constant operands.
254302
255- `operands` contains an entry for every operand of the
256- implementing op with a null attribute if the operand has no constant
257- value or the corresponding attribute if it is a constant.
303+ This method also passes along the constant operands of this op.
304+ `operands` contains an entry for every operand of this op, with a null
305+ attribute if the operand has no constant value .
258306
259- Default implementation simply dispatches to the parent
307+ The default implementation simply dispatches to the parent
260308 `RegionBranchOpInterface`'s `getSuccessorRegions` implementation.
261309 }],
262310 "void", "getSuccessorRegions",
263311 (ins "::llvm::ArrayRef<::mlir::Attribute>":$operands,
264312 "::llvm::SmallVectorImpl<::mlir::RegionSuccessor> &":$regions), [{}],
265- [{
313+ /*defaultImplementation=*/ [{
266314 ::mlir::Operation *op = $_op;
267315 ::llvm::cast<::mlir::RegionBranchOpInterface>(op->getParentOp())
268316 .getSuccessorRegions(op->getParentRegion(), regions);
0 commit comments