[flang-commits] [flang] 57998a6 - [flang][AliasAnalysis] Relax AliasAnalysis for host associated allocatables (#220826)
via flang-commits
flang-commits at lists.llvm.org
Thu Sep 3 09:03:25 PDT 2026
Author: Moazin K.
Date: 2026-09-03T09:03:20-07:00
New Revision: 57998a6047a54643b474d64ca4648d02746a85ca
URL: https://github.com/llvm/llvm-project/commit/57998a6047a54643b474d64ca4648d02746a85ca
DIFF: https://github.com/llvm/llvm-project/commit/57998a6047a54643b474d64ca4648d02746a85ca.diff
LOG: [flang][AliasAnalysis] Relax AliasAnalysis for host associated allocatables (#220826)
Relax AliasAnalysis for host associated allocatables.
FIR alias analysis conservatively returns MayAlias for values with
distinct host-associated origins because their storage may overlap
through EQUIVALENCE.
This change utilizes the fact that an equivalence object cannot be an
allocatable and relaxes the analysis for them. Specifically, if two
values have distinct host associated origin, neither is a pointer or a
target and at least one of them is an allocatable, we can safely declare
them NoAlias. Otherwise, we continue to conservatiely declare them
MayAlias.
Assisted-by: Codex
Added:
Modified:
flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
flang/test/Analysis/AliasAnalysis/alias-analysis-host-assoc.fir
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index 32d95d3e09677..98d92e683a2a7 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -287,6 +287,10 @@ struct AliasAnalysis {
/// Return true, if Pointer attribute is set.
bool isPointer() const;
+ /// Return true if the source originates at a Fortran variable declaration
+ /// with the ALLOCATABLE attribute.
+ bool isDeclaredAllocatable() const;
+
/// Return true, if CrayPointer attribute is set.
bool isCrayPointer() const;
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 4322e9ebcd0d1..4534adb66d748 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -427,6 +427,17 @@ bool AliasAnalysis::Source::isPointer() const {
return attributes.test(Attribute::Pointer);
}
+bool AliasAnalysis::Source::isDeclaredAllocatable() const {
+ auto isAllocatable = [](mlir::Operation *op) {
+ auto var = mlir::dyn_cast_or_null<fir::FortranVariableOpInterface>(op);
+ return var && var.isAllocatable();
+ };
+
+ auto value = origin.u.dyn_cast<mlir::Value>();
+ return (value && isAllocatable(value.getDefiningOp())) ||
+ isAllocatable(origin.instantiationPoint);
+}
+
bool AliasAnalysis::Source::isCrayPointee() const {
return attributes.test(Attribute::CrayPointee);
}
@@ -831,8 +842,19 @@ AliasResult AliasAnalysis::alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
return AliasResult::MayAlias;
}
- // Two host associated accesses may overlap due to an equivalence.
+ // Two host-associated accesses may overlap through EQUIVALENCE, so return
+ // MayAlias conservatively. The exception is distinct data accesses where
+ // at least one is allocatable, since allocatables cannot be EQUIVALENCE
+ // objects, provided neither can participate in pointer association.
if (lhsSrc.kind == SourceKind::HostAssoc) {
+ if (lhsSrc.isData() && rhsSrc.isData() && !lhsSrc.isTargetOrPointer() &&
+ !rhsSrc.isTargetOrPointer() &&
+ (lhsSrc.isDeclaredAllocatable() || rhsSrc.isDeclaredAllocatable())) {
+ LLVM_DEBUG(llvm::dbgs()
+ << " no alias: distinct host-associated data involving "
+ "an allocatable\n");
+ return AliasResult::NoAlias;
+ }
LLVM_DEBUG(llvm::dbgs() << " aliasing because of host association\n");
return AliasResult::MayAlias;
}
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-host-assoc.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-host-assoc.fir
index d570d039432bd..1d26c12de0f0f 100644
--- a/flang/test/Analysis/AliasAnalysis/alias-analysis-host-assoc.fir
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-host-assoc.fir
@@ -409,3 +409,68 @@ fir.global @_QMglobalsEg target : !fir.array<10xi32> {
%0 = fir.undefined !fir.array<10xi32>
fir.has_value %0 : !fir.array<10xi32>
}
+
+// -----
+
+// subroutine test12
+// integer, allocatable :: a(:), b(:)
+// allocate(a(1), b(1))
+// contains
+// subroutine inner()
+// a(1) = b(1)
+// end subroutine inner
+// end subroutine test12
+
+// Distinct host-associated allocatables cannot overlap through EQUIVALENCE.
+// CHECK: test12_a(1)#0 <-> test12_b(1)#0: NoAlias
+func.func @_QFtest12Pinner(%arg0: !fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>> {fir.host_assoc}) attributes {fir.internal_proc} {
+ %c0_i32 = arith.constant 0 : i32
+ %0 = fir.coordinate_of %arg0, %c0_i32 : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %1 = fir.load %0 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<allocatable, host_assoc>, uniq_name = "_QFtest12Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+ %3 = fir.load %2#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %c1 = arith.constant 1 : index
+ %4 = hlfir.designate %3 (%c1) {test.ptr = "test12_a(1)"} : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> !fir.ref<i32>
+
+ %c1_i32 = arith.constant 1 : i32
+ %5 = fir.coordinate_of %arg0, %c1_i32 : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %6 = fir.load %5 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %7:2 = hlfir.declare %6 {fortran_attrs = #fir.var_attrs<allocatable, host_assoc>, uniq_name = "_QFtest12Eb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+ %8 = fir.load %7#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %c1_0 = arith.constant 1 : index
+ %9 = hlfir.designate %8 (%c1_0) {test.ptr = "test12_b(1)"} : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> !fir.ref<i32>
+ return
+}
+
+// -----
+
+// subroutine test13
+// integer, allocatable, target :: a(:)
+// integer, pointer :: p(:)
+// allocate(a(10))
+// p => a
+// contains
+// subroutine inner()
+// a(1) = p(1)
+// end subroutine inner
+// end subroutine test13
+
+// CHECK: test13_a(1)#0 <-> test13_p(1)#0: MayAlias
+func.func @_QFtest13Pinner(%arg0: !fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>> {fir.host_assoc}) attributes {fir.internal_proc} {
+ %c0_i32 = arith.constant 0 : i32
+ %0 = fir.coordinate_of %arg0, %c0_i32 : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %1 = fir.load %0 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>>
+ %2:2 = hlfir.declare %1 {fortran_attrs = #fir.var_attrs<allocatable, target, host_assoc>, uniq_name = "_QFtest13Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+ %3 = fir.load %2#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+ %c1 = arith.constant 1 : index
+ %4 = hlfir.designate %3 (%c1) {test.ptr = "test13_a(1)"} : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> !fir.ref<i32>
+
+ %c1_i32 = arith.constant 1 : i32
+ %5 = fir.coordinate_of %arg0, %c1_i32 : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>
+ %6 = fir.load %5 : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>>
+ %7:2 = hlfir.declare %6 {fortran_attrs = #fir.var_attrs<pointer, host_assoc>, uniq_name = "_QFtest13Ep"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>)
+ %8 = fir.load %7#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>
+ %c1_0 = arith.constant 1 : index
+ %9 = hlfir.designate %8 (%c1_0) {test.ptr = "test13_p(1)"} : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> !fir.ref<i32>
+ return
+}
More information about the flang-commits
mailing list