The current implementation is not very ergonomic or descriptive: It uses std::optional<unsigned> where std::nullopt represents the parent op and unsigned is the region number.
This doesn't give us any useful methods specific to region control flow and makes the code fragile to changes due to now taking the region number into account.
This patch introduces a new type called RegionBranchPoint, replacing all uses of std::optional<unsigned> in the interface. It can be implicitly constructed from a region or a RegionSuccessor, can be compared with a region to check whether the branch point is branching from the parent, adds isParent to check whether we are coming from a parent op and adds RegionSuccessor::parent as a descriptive way to indicate branching from the parent.
FWIW I think it's more idiomatic to have RegionBranchPointer::parent() instead of accessing the singleton directly. It mirrors WalkResult::advance(), LogicalResult::success(), etc.