[flang-commits] [flang] [flang] AliasAnalysis: Fix pointer component logic (PR #94242)

Joel E. Denny via flang-commits flang-commits at lists.llvm.org
Thu Jun 20 07:07:14 PDT 2024


================
@@ -159,21 +193,56 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
     src2->attributes.set(Attribute::Target);
   }
 
-  // Dummy TARGET/POINTER argument may alias with a global TARGET/POINTER.
+  // Two TARGET/POINTERs may alias.
   if (src1->isTargetOrPointer() && src2->isTargetOrPointer() &&
       src1->isData() == src2->isData()) {
     LLVM_DEBUG(llvm::dbgs() << "  aliasing because of target or pointer\n");
     return AliasResult::MayAlias;
   }
 
-  // Box for POINTER component inside an object of a derived type
-  // may alias box of a POINTER object, as well as boxes for POINTER
-  // components inside two objects of derived types may alias.
-  if ((src1->isRecordWithPointerComponent() && src2->isTargetOrPointer()) ||
-      (src2->isRecordWithPointerComponent() && src1->isTargetOrPointer()) ||
-      (src1->isRecordWithPointerComponent() &&
-       src2->isRecordWithPointerComponent())) {
-    LLVM_DEBUG(llvm::dbgs() << "  aliasing because of pointer components\n");
+  // A pointer dummy arg (but not a pointer component of a dummy arg) may alias
+  // a pointer component and thus the associated composite.  That composite
+  // might be a global or another dummy arg.  This is an example of the global
+  // composite case:
+  //
+  // module m
+  //   type t
+  //      real, pointer :: p
+  //   end type
+  //   type(t) :: a
+  //   type(t) :: b
+  // contains
+  //   subroutine test(p)
+  //     real, pointer :: p
+  //     p = 42
+  //     a = b
+  //     print *, p
+  //   end subroutine
+  // end module
+  // program
+  //   use m
+  //   real, target :: x1 = 1
+  //   real, target :: x2 = 2
+  //   a%p => x1
+  //   b%p => x2
+  //   call test(a%p)
+  // end
+  //
+  // The dummy argument p is an alias for a%p, even for the purposes of pointer
+  // association during the assignment a = b.  Thus, the program should print 2.
+  if ((isRecordWithPointerComponent(val1->getType()) &&
+       src1->kind != SourceKind::Allocate &&
+       src2->kind == SourceKind::Argument &&
+       src2->attributes.test(Attribute::Pointer) && !src2->isData() &&
+       !isRecordWithPointerComponent(src2->valueType)) ||
----------------
jdenny-ornl wrote:

> `a` in my example does not need target because it is not a dummy argument, so `15.5.2.14` does not restrict the effects on it. `15.5.2.14` restrict the effects on `c`, so it only matters that `c` has this attribute to allow `c` to be effected by changes on `a`.

Thanks, but would you please help me to understand how the spec says that?  Or maybe the spec is stricter than defacto behavior?  In particular, when the dummy argument (`c`) has the TARGET attribute, one condition in the spec to permit aliasing is that the _actual argument_ (`a`) is a target.  Given the definition of "target" that I quoted, how is `a` a target in your example?
> 
> I agree this is not a very well known aspect, but it is what is, and other compiler respect it (if you do A= B with two TARGET assumed-shape, you should observe that all compiler will cope with the case where A an B alias, even f not POINTERs are involved).

I assume this doesn't refer to the `a` and `b` in your example given that neither have TARGET.  In this new example, are A and B both dummy arguments, both with TARGET?

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


More information about the flang-commits mailing list