[flang-commits] [flang] [flang] Add initial support for RegionBranchOpInterface to AA (PR #196132)

Razvan Lupusoru via flang-commits flang-commits at lists.llvm.org
Thu May 7 07:14:53 PDT 2026


================
@@ -141,6 +142,156 @@ static fir::AliasAnalysis::Source getSourceForACCMappedValue(
   return source;
 }
 
+/// Predecessor SSA values that may define a result of \p branch when control
+/// continues in the parent region (same mapping as
+/// `LocalAliasAnalysis::collectUnderlyingAddressValues2` for
+/// `RegionSuccessor::parent()`).
+static void getRegionBranchPredecessorValuesForParentResult(
+    mlir::RegionBranchOpInterface branch, mlir::OpResult result,
+    llvm::SmallVectorImpl<mlir::Value> &out) {
+  mlir::RegionSuccessor parentSucc = mlir::RegionSuccessor::parent();
+  mlir::Value inputValue = result;
+  unsigned inputIndex = result.getResultNumber();
+  mlir::ValueRange inputs = branch.getSuccessorInputs(parentSucc);
+  if (inputs.empty()) {
+    out.push_back(inputValue);
+    return;
+  }
+  unsigned firstInputIndex, lastInputIndex;
+  if (mlir::isa<mlir::BlockArgument>(inputs[0])) {
+    firstInputIndex = mlir::cast<mlir::BlockArgument>(inputs[0]).getArgNumber();
+    lastInputIndex =
+        mlir::cast<mlir::BlockArgument>(inputs.back()).getArgNumber();
+  } else {
+    firstInputIndex = mlir::cast<mlir::OpResult>(inputs[0]).getResultNumber();
+    lastInputIndex =
+        mlir::cast<mlir::OpResult>(inputs.back()).getResultNumber();
+  }
+  if (firstInputIndex > inputIndex || lastInputIndex < inputIndex) {
+    out.push_back(inputValue);
+    return;
+  }
+  branch.getPredecessorValues(parentSucc, inputIndex - firstInputIndex, out);
+}
+
+/// True when \p src's tracked origin value is an SSA result of an operation
+/// nested under \p branch's regions.
+static bool originIsInsideRegionBranch(mlir::RegionBranchOpInterface branch,
+                                       const fir::AliasAnalysis::Source &src) {
+  const fir::AliasAnalysis::Source::SourceOrigin &origin = src.origin;
+  if (llvm::isa<mlir::SymbolRefAttr>(origin.u))
+    return false;
+  mlir::Value originVal = llvm::cast<mlir::Value>(origin.u);
+  if (mlir::isa<mlir::BlockArgument>(originVal))
+    return false;
+  mlir::Operation *defOp = originVal.getDefiningOp();
+  if (!defOp)
+    return false;
+  return branch.getOperation()->isProperAncestor(defOp);
+}
+
+/// Conservative join of memory sources from region-branch predecessors.
+static fir::AliasAnalysis::Source mergeRegionBranchPredecessorSources(
+    llvm::ArrayRef<fir::AliasAnalysis::Source> sources,
+    mlir::Value fallbackValue, mlir::Type fallbackType, bool followingData) {
+  assert(!sources.empty() && "expected at least one predecessor source");
+
+  // For kind, origin, attributes, isApproximate/accessPath, valueType, we
+  // capture if all of the sources have exactly the same value.
+  bool allKindsSame =
+      llvm::all_of(sources, [&](const fir::AliasAnalysis::Source &s) {
+        return s.kind == sources[0].kind;
+      });
+  bool allOriginsSame =
+      llvm::all_of(sources, [&](const fir::AliasAnalysis::Source &s) {
+        return s.origin == sources[0].origin;
+      });
+  bool allAttrsSame =
+      llvm::all_of(sources, [&](const fir::AliasAnalysis::Source &s) {
+        return s.attributes == sources[0].attributes;
+      });
+  bool allPathsSame =
+      llvm::all_of(sources, [&](const fir::AliasAnalysis::Source &s) {
+        return s.accessPath.isApproximate ==
+                   sources[0].accessPath.isApproximate &&
+               s.accessPath.steps == sources[0].accessPath.steps;
+      });
+  bool allTypesSame =
+      llvm::all_of(sources, [&](const fir::AliasAnalysis::Source &s) {
+        return s.valueType == sources[0].valueType;
+      });
+
+  // For approximateSource and isCapturedInInternalProcedure, we mark them
+  // as true if any of the sources are true.
+  bool mergedApprox =
+      llvm::any_of(sources, [](const fir::AliasAnalysis::Source &s) {
+        return s.approximateSource;
+      });
+  bool mergedCaptured =
+      llvm::any_of(sources, [](const fir::AliasAnalysis::Source &s) {
+        return s.isCapturedInInternalProcedure;
+      });
+
+  fir::AliasAnalysis::SourceKind mergedKind;
+  fir::AliasAnalysis::Source::Attributes mergedAttrs;
+  if (!allKindsSame) {
+    mergedKind = fir::AliasAnalysis::SourceKind::Unknown;
+    mergedAttrs = {};
+  } else if (!allAttrsSame) {
+    mergedKind = fir::AliasAnalysis::SourceKind::Unknown;
+    mergedAttrs = {};
+  } else if (!allOriginsSame) {
+    // Same kind and attributes on every path, but different concrete origins.
+    // Since origins are different, for most cases fall back to Indirect here.
+    // However, for Allocate, we want to keep the information about this being
+    // an Allocate as long as all are defined inside the region's branches
+    // because then they are all unique and thus cannot alias anything outside
+    // the region (this is key here - because this only holds when comparing
+    // region's result only with outside values not the origins themselves).
+    // TODO: An origin list would be better to preserve this information
+    // more accurately instead of a single origin.
+    auto branchOp = mlir::dyn_cast<mlir::RegionBranchOpInterface>(
+        mlir::cast<mlir::OpResult>(fallbackValue).getOwner());
+    assert(branchOp && "merge region-branch sources expects branch op result");
+    unsigned originsOutsideBranch =
+        llvm::count_if(sources, [&](const fir::AliasAnalysis::Source &s) {
+          return !originIsInsideRegionBranch(branchOp, s);
+        });
----------------
razvanlupusoru wrote:

Done :)

https://github.com/llvm/llvm-project/pull/196132


More information about the flang-commits mailing list