[flang-commits] [flang] [flang] Respect record type changes in FIR alias analysis access paths (PR #231655)

Tom Eccles via flang-commits flang-commits at lists.llvm.org
Thu Oct 15 04:32:39 PDT 2026


================
@@ -591,40 +669,43 @@ static bool noAliasBasedOnType(mlir::Value lhs, mlir::Value rhs) {
 /// source's POINTER attribute reflects the component traversed during the
 /// walk, not the root variable, so we check only TARGET on the source.
 ///
-/// One exception: if BOTH sides end with a PointerDeref, the two pointers
-/// could independently be associated with the same third-party TARGET
-/// variable, so we conservatively return false.
+/// One exception: if BOTH sides continue through a PointerDeref, the two
+/// pointers could independently be associated with the same third-party
+/// TARGET variable, so such steps do not prove disjointness.
 static bool pathsDivergeAtComponent(const fir::AliasAnalysis::Source &lhsSrc,
                                     const fir::AliasAnalysis::Source &rhsSrc) {
   using PathStep = fir::AliasAnalysis::Source::PathStep;
+  if (lhsSrc.accessPath.storageDecl != rhsSrc.accessPath.storageDecl)
+    return false;
   auto &lhsSteps = lhsSrc.accessPath.steps;
   auto &rhsSteps = rhsSrc.accessPath.steps;
-  size_t minLen = std::min(lhsSteps.size(), rhsSteps.size());
-  for (size_t i = 0; i < minLen; ++i) {
-    if (lhsSteps[i].kind == PathStep::Kind::Component &&
-        rhsSteps[i].kind == PathStep::Kind::Component &&
-        lhsSteps[i].component != rhsSteps[i].component) {
-      auto hasPtrDerefAfter = [](llvm::ArrayRef<PathStep> steps, size_t from) {
-        for (size_t j = from; j < steps.size(); ++j)
-          if (steps[j].kind == PathStep::Kind::PointerDeref)
-            return true;
-        return false;
-      };
-      bool lhsHasPtrDeref = hasPtrDerefAfter(lhsSteps, i + 1);
-      bool rhsHasPtrDeref = hasPtrDerefAfter(rhsSteps, i + 1);
+  auto hasPtrDeref = [](llvm::ArrayRef<PathStep> steps) {
+    return llvm::any_of(steps, [](const PathStep &s) {
+      return s.kind == PathStep::Kind::PointerDeref;
+    });
+  };
+  for (size_t i = 0; i < lhsSteps.size(); ++i) {
+    if (lhsSteps[i].kind != PathStep::Kind::Component)
+      continue;
+    for (size_t j = 0; j < rhsSteps.size(); ++j) {
+      if (rhsSteps[j].kind != PathStep::Kind::Component ||
+          !componentsAreDisjoint(lhsSteps[i], rhsSteps[j]))
+        continue;
+      bool lhsHasPtrDeref =
+          hasPtrDeref(llvm::ArrayRef<PathStep>(lhsSteps).drop_front(i + 1));
+      bool rhsHasPtrDeref =
+          hasPtrDeref(llvm::ArrayRef<PathStep>(rhsSteps).drop_front(j + 1));
       if (lhsHasPtrDeref && rhsHasPtrDeref)
-        return false;
+        continue;
       if (lhsHasPtrDeref || rhsHasPtrDeref) {
-        for (size_t j = 0; j < i; ++j)
-          if (lhsSteps[j].kind == PathStep::Kind::PointerDeref)
-            return false;
+        if (hasPtrDeref(llvm::ArrayRef<PathStep>(lhsSteps).take_front(i)) ||
+            hasPtrDeref(llvm::ArrayRef<PathStep>(rhsSteps).take_front(j)))
+          continue;
         if (lhsSrc.isTarget() || rhsSrc.isTarget())
----------------
tblah wrote:

My AI reviewer found that with `x%pointer => x%allocatable`, it incorrectly treats `x%allocatable%v` and `x%pointer%v` as disjoint. 

I think this missed this case where the TARGET attribute is present.

Full (AI-written) reproducer:
```
module m
  type base
    integer :: v(4)
  end type
  type, extends(base) :: child
    type(base), allocatable :: a
    type(base), pointer :: p
  end type
contains
  subroutine shift(x)
    type(child), target :: x
    x%a%v(2:4) = x%p%v(1:3)
  end subroutine
end module
program main
  use m
  type(child), target :: x
  allocate(x%a)
  x%a%v = [1, 2, 3, 4]
  x%p => x%a
  call shift(x)
  print *, x%a%v
  if (any(x%a%v /= [1, 1, 2, 3])) stop 1
end program
```

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


More information about the flang-commits mailing list