[flang-commits] [flang] [flang] Add initial support for RegionBranchOpInterface to AA (PR #196132)
via flang-commits
flang-commits at lists.llvm.org
Thu May 7 01:41:00 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);
+ });
----------------
jeanPerier wrote:
`bool originsOutsideBranch = llvm:any_of ...`
https://github.com/llvm/llvm-project/pull/196132
More information about the flang-commits
mailing list