================
@@ -583,3 +602,467 @@ Region *mlir::getEnclosingRepetitiveRegion(Value value) {
   LDBG() << "No enclosing repetitive region found for value";
   return nullptr;
 }
+
+/// Return "true" if `a` can be used in lieu of `b`, where `b` is a region
+/// successor input and `a` is a "possible value" of `b`. Possible values are
+/// successor operand values that are (maybe transitively) forwarded to `b`.
+static bool isDefinedBefore(Operation *regionBranchOp, Value a, Value b) {
+  assert((b.getDefiningOp() == regionBranchOp ||
+          b.getParentRegion()->getParentOp() == regionBranchOp) &&
+         "b must be a region successor input");
+
+  // Case 1: `a` is defined inside of the region branch op. `a` must be
+  // directly nested in the region branch op. Otherwise, it could not have
+  // been among the possible values for a region successor input.
+  if (a.getParentRegion()->getParentOp() == regionBranchOp) {
+    // Case 1.1: If `b` is a result of the region branch op, `a` is not in
+    // scope for `b`.
+    // Example:
+    // %b = region_op({
+    // ^bb0(%a1: ...):
+    //   %a2 = ...
+    // })
+    if (isa<OpResult>(b))
+      return false;
+
+    // Case 1.2: `b` is an entry block argument of a region. `a` is in scope
+    // for `b` only if it is also an entry block argument of the same region.
+    // Example:
+    // region_op({
+    // ^bb0(%b: ..., %a: ...):
+    //   ...
+    // })
+    assert(isa<BlockArgument>(b) && "b must be a block argument");
+    return isa<BlockArgument>(a) && cast<BlockArgument>(a).getOwner() ==
+                                        cast<BlockArgument>(b).getOwner();
+  }
+
+  // Case 2: `a` is defined outside of the region branch op. In that case, we
+  // can safely assume that `a` was defined before `b`. Otherwise, it could not
+  // be among the possible values for a region successor input.
+  // Example:
+  // {   <- %a1 parent region begins here.
+  // ^bb0(%a1: ...):
+  //   %a2 = ...
+  //   %b1 = reigon_op({
+  //   ^bb1(%b2: ...):
+  //     ...
+  //   })
+  // }
+  return true;
+}
+
+/// Compute all non-successor input values that a successor input could have
+/// based on the given successor input to successor operand mapping.
+///
+/// Example 1:
+/// %r = scf.for ... iter_args(%arg0 = %0) -> ... {
+///   scf.yield %arg0 : ...
+/// }
+/// getPossibleValuesOfSuccessorInput(%arg0) = {%0}
+/// getPossibleValuesOfSuccessorInput(%r) = {%0}
+///
+/// Example 2:
+/// %r = scf.for ... iter_args(%arg0 = %0) -> ... {
+///   ...
+///   scf.yield %1 : ...
+/// }
+/// getPossibleValuesOfSuccessorInput(%arg0) = {%0, %1}
+/// getPossibleValuesOfSuccessorInput(%r) = {%0, %1}
+static llvm::SmallDenseSet<Value> computePossibleValuesOfSuccessorInput(
----------------
linuxlonelyeagle wrote:

The term 'values' in computePossibleValuesOfSuccessorInput is a bit confusing; 
perhaps we could come up with a better name.

https://github.com/llvm/llvm-project/pull/174094
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to