diff --git a/mlir/include/mlir/Dialect/SCF/SCF.h b/mlir/include/mlir/Dialect/SCF/SCF.h --- a/mlir/include/mlir/Dialect/SCF/SCF.h +++ b/mlir/include/mlir/Dialect/SCF/SCF.h @@ -49,6 +49,11 @@ /// value is not an induction variable, then return nullptr. ParallelOp getParallelForInductionVarOwner(Value val); +/// Return true if ops a and b (or their ancestors) are in mutually exclusive +/// regions/blocks of an IfOp. +// TODO: Consider moving this functionality to RegionBranchOpInterface. +bool insideMutableExclusiveBranches(Operation *a, Operation *b); + /// An owning vector of values, handy to return from functions. using ValueVector = std::vector; using LoopVector = std::vector; diff --git a/mlir/lib/Dialect/SCF/SCF.cpp b/mlir/lib/Dialect/SCF/SCF.cpp --- a/mlir/lib/Dialect/SCF/SCF.cpp +++ b/mlir/lib/Dialect/SCF/SCF.cpp @@ -1009,6 +1009,26 @@ // IfOp //===----------------------------------------------------------------------===// +bool mlir::scf::insideMutableExclusiveBranches(Operation *a, Operation *b) { + assert(a && "expected non-empty operation"); + assert(b && "expected non-empty operation"); + + IfOp ifOp = a->getParentOfType(); + while (ifOp) { + // Check if b is inside ifOp. (We already know that a is.) + if (ifOp->isProperAncestor(b)) + // b is contained in ifOp. a and b are in mutually exclusive branches if + // they are in different blocks of ifOp. + return static_cast(ifOp.thenBlock()->findAncestorOpInBlock(*a)) != + static_cast(ifOp.thenBlock()->findAncestorOpInBlock(*b)); + // Check next enclosing IfOp. + ifOp = ifOp->getParentOfType(); + } + + // Could not find a common IfOp among a's and b's ancestors. + return false; +} + void IfOp::build(OpBuilder &builder, OperationState &result, Value cond, bool withElseRegion) { build(builder, result, /*resultTypes=*/llvm::None, cond, withElseRegion);