Comments/Questions about scf.execute_region_op

I have a couple of questions/comments about the scf.execute_region_op. 'scf' Dialect - MLIR

Is there an implicit assumption that the terminator will always be an scf.yield op? Currently, the canonicalizer inlines the region (if possible). And I think this inlining will only work with scf.yield or yield like operations.

If there is such an assumption would it be OK to check that in the verifier? Or if there is no such assumption, is it OK to not canonicalize/inline if the terminator is some other operation?

I think there is such an assumption and it should be checked in the verifier. We need a mechanism to flow values from inside the region to the results of scf.execute_region operation itself, and scf.yield has exactly that semantics.

If we really wanted to relax this, we cannot just take arbitrary terminators but rather only ops that are known to flow their operands to the parent region via the BranchOpInterface.

A check in the verifier is actually missing for this one. The other scf ops just have a SingleBlockImplicitTerminator<"scf::YieldOp"> which took care of it. However, the execute_region op can have multiple blocks just like a FuncOp and so we can’t use that. The scf.yield op is all that’s needed for its terminator given what it models.

In fact, even the func op is missing such a verifier for its terminator. The following IR parses and verifies, but the terminator should be restricted to the return op I believe.

func @call() {
  "test.return"() : () -> ()
}
1 Like