[flang-commits] [flang] [flang] AliasAnalysis: distinguish addr of arg vs. addr in arg (PR #87723)

Joel E. Denny via flang-commits flang-commits at lists.llvm.org
Thu Apr 18 10:49:33 PDT 2024


https://github.com/jdenny-ornl updated https://github.com/llvm/llvm-project/pull/87723

>From 91def8cd94aadf6f1909c63277aea4364c8907e1 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Thu, 4 Apr 2024 12:41:05 -0400
Subject: [PATCH 1/5] [flang] AliasAnalysis: distinguish addr of arg vs. addr
 in arg

For example, in the following program, the relationship between the
address *in* arg (dynamically the address of x's alloca) and the
address *of* arg (dynamically the address of p's alloca) is not
MustAlias, as determined without this patch:

```
subroutine f()
  real, pointer :: p
  real, target :: x
  p => x
  call g(p)
end subroutine f
subroutine g(arg)
  real, pointer :: arg
end subroutine g
```

Generally extend test coverage for HLFIR-based alias analysis for
addresses extracted from pointers.
---
 .../flang/Optimizer/Analysis/AliasAnalysis.h  |  4 +-
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  | 20 +++--
 .../AliasAnalysis/alias-analysis-2.fir        |  2 +-
 .../alias-analysis-box-addr-load/arg.fir      | 90 +++++++++++++++++++
 4 files changed, 108 insertions(+), 8 deletions(-)
 create mode 100644 flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir

diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index dfcafe88fee1b5..dd4eb363cc7277 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -36,8 +36,8 @@ struct AliasAnalysis {
              /// Represents memory allocated outside of a function
              /// and passed to the function via host association tuple.
              HostAssoc,
-             /// Represents direct memory access whose source cannot be further
-             /// determined
+             /// Memory address retrieved from a box, perhaps from a global or
+             /// an argument.
              Direct,
              /// Represents memory allocated by unknown means and
              /// with the memory address defined by a memory reading
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index e144640081cbf3..f0af0dd547f980 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -91,8 +91,14 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
   LLVM_DEBUG(llvm::dbgs() << "AliasAnalysis::alias\n";
              llvm::dbgs() << "  lhs: " << lhs << "\n";
              llvm::dbgs() << "  lhsSrc: " << lhsSrc << "\n";
+             llvm::dbgs() << "  lhsSrc kind: " << EnumToString(lhsSrc.kind) << "\n";
+             llvm::dbgs() << "  lhsSrc pointer: " << lhsSrc.attributes.test(Attribute::Pointer) << "\n";
+             llvm::dbgs() << "  lhsSrc target: " << lhsSrc.attributes.test(Attribute::Target) << "\n";
              llvm::dbgs() << "  rhs: " << rhs << "\n";
              llvm::dbgs() << "  rhsSrc: " << rhsSrc << "\n";
+             llvm::dbgs() << "  rhsSrc kind: " << EnumToString(rhsSrc.kind) << "\n";
+             llvm::dbgs() << "  rhsSrc pointer: " << rhsSrc.attributes.test(Attribute::Pointer) << "\n";
+             llvm::dbgs() << "  rhsSrc target: " << rhsSrc.attributes.test(Attribute::Target) << "\n";
              llvm::dbgs() << "\n";);
 
   // Indirect case currently not handled. Conservatively assume
@@ -101,8 +107,10 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
     return AliasResult::MayAlias;
   }
 
-  // SourceKind::Direct is set for the addresses wrapped in a global boxes.
-  // ie: fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
+  // SourceKind::Direct is set for the addresses wrapped in a box, perhaps from
+  // a global or an argument.
+  // e.g.: fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
+  // e.g.: %arg0: !fir.ref<!fir.box<!fir.ptr<f32>>>
   // Though nothing is known about them, they would only alias with targets or
   // pointers
   bool directSourceToNonTargetOrPointer = false;
@@ -399,16 +407,18 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
   if (!defOp && type == SourceKind::Unknown)
     // Check if the memory source is coming through a dummy argument.
     if (isDummyArgument(v)) {
-      type = SourceKind::Argument;
       ty = v.getType();
       if (fir::valueHasFirAttribute(v, fir::getTargetAttrName()))
         attributes.set(Attribute::Target);
-
       if (Source::isPointerReference(ty))
         attributes.set(Attribute::Pointer);
+      if (followBoxAddr && attributes.test(Attribute::Pointer))
+        type = SourceKind::Direct;
+      else
+        type = SourceKind::Argument;
     }
 
-  if (type == SourceKind::Global || type == SourceKind::Direct)
+  if (global)
     return {global, type, ty, attributes, approximateSource};
 
   return {v, type, ty, attributes, approximateSource};
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
index 31459ef21d947c..d915ba9d27905a 100644
--- a/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
@@ -44,7 +44,7 @@
 // pointer arguments
 // CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias
 // CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias
-// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MustAlias
+// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MayAlias
 // CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias
 
 func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<f32> {fir.bindc_name = "v2", fir.target}, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
new file mode 100644
index 00000000000000..de1b478fa9599e
--- /dev/null
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
@@ -0,0 +1,90 @@
+// Check aliasing with the address passed via a pointer dummy argument.
+
+// Use --mlir-disable-threading so that the AA queries are serialized
+// as well as its diagnostic output.
+// RUN: fir-opt %s \
+// RUN:   -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' \
+// RUN:   --mlir-disable-threading 2>&1 | FileCheck %s
+
+// subroutine test(p0, p1, arr, t_arr, alloc, t_alloc)
+//   real, pointer :: p0, p1
+//   real :: arr(:)
+//   real, target :: t_arr(:)
+//   real, allocatable :: alloc
+//   real, allocatable, target :: t_alloc
+//   real, target :: t
+//   real :: v
+//   v = p0
+//   v = p1
+//   v = arr(1)
+//   v = t_arr(1)
+//   v = alloc
+//   v = t_alloc
+// end subroutine test
+
+// CHECK-LABEL: Testing : "_QPtest"
+
+// The address in a pointer can alias the address in another pointer or the
+// address of a target but not the address of other variables.
+// CHECK-DAG: t.addr#0 <-> p0.tgt_addr#0: MayAlias
+// CHECK-DAG: t.addr#0 <-> p1.tgt_addr#0: MayAlias
+// CHECK-DAG: v.addr#0 <-> p0.tgt_addr#0: NoAlias
+// CHECK-DAG: v.addr#0 <-> p1.tgt_addr#0: NoAlias
+// CHECK-DAG: p0.tgt_addr#0 <-> p1.tgt_addr#0: MayAlias
+
+// Determining whether the address *in* a pointer can alias the address *of* a
+// pointer is not yet handled.  In the past, when it was the same pointer, that
+// relationship was mistakenly determined to be MustAlias.
+// CHECK-DAG: p0.tgt_addr#0 <-> func.region0#0: MayAlias
+// CHECK-DAG: p0.tgt_addr#0 <-> func.region0#1: MayAlias
+// CHECK-DAG: p1.tgt_addr#0 <-> func.region0#0: MayAlias
+// CHECK-DAG: p1.tgt_addr#0 <-> func.region0#1: MayAlias
+
+// For some cases, AliasAnalysis analyzes hlfir.designate like fir.box_addr, so
+// make sure it doesn't mistakenly see arr(1).addr as an address that was loaded
+// from a pointer and that could alias something.  However, t_arr is a target.
+// CHECK-DAG: p0.tgt_addr#0 <-> arr(1).addr#0: NoAlias
+// CHECK-DAG: p0.tgt_addr#0 <-> t_arr(1).addr#0: MayAlias
+
+// Like a pointer, an allocatable contains an address, but an allocatable is not
+// a pointer and so cannot alias pointers.  However, t_alloc is a target.
+// CHECK-DAG: p0.tgt_addr#0 <-> alloc.tgt_addr#0: NoAlias
+// CHECK-DAG: p0.tgt_addr#0 <-> t_alloc.tgt_addr#0: MayAlias
+
+func.func @_QPtest(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p0"}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg2: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "arr"}, %arg3: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "t_arr", fir.target}, %arg4: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "alloc"}, %arg5: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "t_alloc", fir.target}) attributes {test.ptr="func"} {
+  %0:2 = hlfir.declare %arg4 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEalloc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
+  %1:2 = hlfir.declare %arg2 {uniq_name = "_QFtestEarr"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+  %2:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp0"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
+  %3:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp1"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
+  %4 = fir.alloca f32 {bindc_name = "t", fir.target, uniq_name = "_QFtestEt"}
+  %5:2 = hlfir.declare %4 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtestEt", test.ptr="t.addr"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %6:2 = hlfir.declare %arg5 {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QFtestEt_alloc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
+  %7:2 = hlfir.declare %arg3 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtestEt_arr"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+  %8 = fir.alloca f32 {bindc_name = "v", uniq_name = "_QFtestEv"}
+  %9:2 = hlfir.declare %8 {uniq_name = "_QFtestEv", test.ptr="v.addr"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+  %10 = fir.load %2#0 : !fir.ref<!fir.box<!fir.ptr<f32>>>
+  %11 = fir.box_addr %10 {test.ptr="p0.tgt_addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
+  %12 = fir.load %11 : !fir.ptr<f32>
+  hlfir.assign %12 to %9#0 : f32, !fir.ref<f32>
+  %13 = fir.load %3#0 : !fir.ref<!fir.box<!fir.ptr<f32>>>
+  %14 = fir.box_addr %13 {test.ptr="p1.tgt_addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
+  %15 = fir.load %14 : !fir.ptr<f32>
+  hlfir.assign %15 to %9#0 : f32, !fir.ref<f32>
+  %c1 = arith.constant 1 : index
+  %16 = hlfir.designate %1#0 (%c1) {test.ptr="arr(1).addr"} : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+  %17 = fir.load %16 : !fir.ref<f32>
+  hlfir.assign %17 to %9#0 : f32, !fir.ref<f32>
+  %c1_0 = arith.constant 1 : index
+  %18 = hlfir.designate %7#0 (%c1_0) {test.ptr="t_arr(1).addr"} : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+  %19 = fir.load %18 : !fir.ref<f32>
+  hlfir.assign %19 to %9#0 : f32, !fir.ref<f32>
+  %20 = fir.load %0#0 : !fir.ref<!fir.box<!fir.heap<f32>>>
+  %21 = fir.box_addr %20 {test.ptr="alloc.tgt_addr"} : (!fir.box<!fir.heap<f32>>) -> !fir.heap<f32>
+  %22 = fir.load %21 : !fir.heap<f32>
+  hlfir.assign %22 to %9#0 : f32, !fir.ref<f32>
+  %23 = fir.load %6#0 : !fir.ref<!fir.box<!fir.heap<f32>>>
+  %24 = fir.box_addr %23 {test.ptr="t_alloc.tgt_addr"} : (!fir.box<!fir.heap<f32>>) -> !fir.heap<f32>
+  %25 = fir.load %24 : !fir.heap<f32>
+  hlfir.assign %25 to %9#0 : f32, !fir.ref<f32>
+  return
+}

>From b4124cfdbaa89f3f87017bedd3db56fc3e3b49ea Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Fri, 5 Apr 2024 16:54:49 -0400
Subject: [PATCH 2/5] Fix case of allocatable arg

The address in it should be a `SourceKind::Direct` not a
`SourceKind::Argument`.  The fix is to set `SourceKind::Direct` in the
case of `!fir.heap` besides just pointers.

An effect is that the address *in* it cannot alias the address *of*
it.  flang/test/Analysis/AliasAnalysis/alias-analysis-8.fir expects
the same relationship in the case of allocatable globals.

Extend AddAliasTags to handle the case of `SourceKind::Direct` for an
arg, and update the occurrence in flang/test/Transforms/tbaa2.fir.
---
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  2 +-
 .../lib/Optimizer/Transforms/AddAliasTags.cpp | 26 ++++++++++++++++---
 .../alias-analysis-box-addr-load/arg.fir      |  8 ++++--
 flang/test/Transforms/tbaa2.fir               |  4 +--
 4 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index f0af0dd547f980..efe573d0b01939 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -412,7 +412,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
         attributes.set(Attribute::Target);
       if (Source::isPointerReference(ty))
         attributes.set(Attribute::Pointer);
-      if (followBoxAddr && attributes.test(Attribute::Pointer))
+      if (followBoxAddr && fir::isa_ref_type(ty))
         type = SourceKind::Direct;
       else
         type = SourceKind::Argument;
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 684aa4462915e5..5c6d3e47492762 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -171,10 +171,28 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
                                         << " at " << *op << "\n");
       tag = state.getFuncTree(func).directDataTree.getTag(name);
     } else {
-      // SourceKind::Direct is likely to be extended to cases which are not a
-      // SymbolRefAttr in the future
-      LLVM_DEBUG(llvm::dbgs().indent(2) << "Can't get name for direct "
-                                        << source << " at " << *op << "\n");
+      bool sourceIsDummyArgument = false;
+      if (auto blockArg =
+              source.u.get<mlir::Value>().dyn_cast<mlir::BlockArgument>())
+        sourceIsDummyArgument = blockArg.getOwner()->isEntryBlock();
+      if (sourceIsDummyArgument) {
+        std::string name = getFuncArgName(source.u.get<mlir::Value>());
+        if (!name.empty()) {
+          LLVM_DEBUG(llvm::dbgs().indent(2)
+                     << "Found reference to direct from dummy argument " << name
+                     << " at " << *op << "\n");
+          tag = state.getFuncTree(func).directDataTree.getTag(name);
+        } else {
+          LLVM_DEBUG(llvm::dbgs().indent(2)
+                     << "WARN: for direct, couldn't find a name for dummy "
+                     << "argument " << *op << "\n");
+        }
+      } else {
+        // SourceKind::Direct is likely to be extended to more cases in the
+        // future
+        LLVM_DEBUG(llvm::dbgs().indent(2) << "Can't get name for direct "
+                                          << source << " at " << *op << "\n");
+      }
     }
 
     // TBAA for local allocations
diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
index de1b478fa9599e..b97a712360124a 100644
--- a/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
@@ -4,7 +4,7 @@
 // as well as its diagnostic output.
 // RUN: fir-opt %s \
 // RUN:   -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' \
-// RUN:   --mlir-disable-threading 2>&1 | FileCheck %s
+// RUN:   --mlir-disable-threading 2>&1 | FileCheck -match-full-lines %s
 
 // subroutine test(p0, p1, arr, t_arr, alloc, t_alloc)
 //   real, pointer :: p0, p1
@@ -51,8 +51,12 @@
 // CHECK-DAG: p0.tgt_addr#0 <-> alloc.tgt_addr#0: NoAlias
 // CHECK-DAG: p0.tgt_addr#0 <-> t_alloc.tgt_addr#0: MayAlias
 
+// The address *in* an allocatable cannot alias the address *of* that
+// allocatable.
+// CHECK-DAG: alloc#0 <-> alloc.tgt_addr#0: NoAlias
+
 func.func @_QPtest(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p0"}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg2: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "arr"}, %arg3: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "t_arr", fir.target}, %arg4: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "alloc"}, %arg5: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "t_alloc", fir.target}) attributes {test.ptr="func"} {
-  %0:2 = hlfir.declare %arg4 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEalloc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
+  %0:2 = hlfir.declare %arg4 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEalloc", test.ptr="alloc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
   %1:2 = hlfir.declare %arg2 {uniq_name = "_QFtestEarr"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
   %2:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp0"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
   %3:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp1"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
diff --git a/flang/test/Transforms/tbaa2.fir b/flang/test/Transforms/tbaa2.fir
index ab39f65cdade70..13b7a876fa3584 100644
--- a/flang/test/Transforms/tbaa2.fir
+++ b/flang/test/Transforms/tbaa2.fir
@@ -48,14 +48,14 @@
 // CHECK: #[[ANY_ACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
 // CHECK: #[[ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY_ACCESS]], 0>}>
 // CHECK: #[[ANY_GLBL:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[ANY_DATA]], 0>}>
-// CHECK: #[[ANY_ARG:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[ANY_DATA]], 0>}>
 // CHECK: #[[ANY_DIRECT:.+]] = #llvm.tbaa_type_desc<id = "direct data", members = {<#[[ANY_DATA]], 0>}>
+// CHECK: #[[ANY_ARG:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[ANY_DATA]], 0>}>
 // CHECK: #[[GLBL_ZSTART:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodEzstart", members = {<#[[ANY_GLBL]], 0>}>
 // CHECK: #[[GLBL_ZSTOP:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodEzstop", members = {<#[[ANY_GLBL]], 0>}>
 // CHECK: #[[GLBL_YSTART:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodEystart", members = {<#[[ANY_GLBL]], 0>}>
 // CHECK: #[[GLBL_YSTOP:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodEystop", members = {<#[[ANY_GLBL]], 0>}>
 // CHECK: #[[GLBL_XSTART:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodExstart", members = {<#[[ANY_GLBL]], 0>}>
-// CHECK: #[[ARG_LOW:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeElow", members = {<#[[ANY_ARG]], 0>}>
+// CHECK: #[[ARG_LOW:.+]] = #llvm.tbaa_type_desc<id = "direct data/_QMmodFcalleeElow", members = {<#[[ANY_DIRECT]], 0>}>
 // CHECK: #[[DIRECT_A:.+]] = #llvm.tbaa_type_desc<id = "direct data/_QMmodEa", members = {<#[[ANY_DIRECT]], 0>}>
 // CHECK: #[[DIRECT_B:.+]] = #llvm.tbaa_type_desc<id = "direct data/_QMmodEb", members = {<#[[ANY_DIRECT]], 0>}>
 // CHECK: #[[ARG_Z:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeEz", members = {<#[[ANY_ARG]], 0>}>

>From fd358afe3d255af81908975aeaf8b323b5a76c13 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Fri, 5 Apr 2024 16:55:13 -0400
Subject: [PATCH 3/5] Apply clang-format

---
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  | 29 +++++++++++--------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index efe573d0b01939..f6a4795feb58bc 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -88,18 +88,23 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
   auto lhsSrc = getSource(lhs);
   auto rhsSrc = getSource(rhs);
   bool approximateSource = lhsSrc.approximateSource || rhsSrc.approximateSource;
-  LLVM_DEBUG(llvm::dbgs() << "AliasAnalysis::alias\n";
-             llvm::dbgs() << "  lhs: " << lhs << "\n";
-             llvm::dbgs() << "  lhsSrc: " << lhsSrc << "\n";
-             llvm::dbgs() << "  lhsSrc kind: " << EnumToString(lhsSrc.kind) << "\n";
-             llvm::dbgs() << "  lhsSrc pointer: " << lhsSrc.attributes.test(Attribute::Pointer) << "\n";
-             llvm::dbgs() << "  lhsSrc target: " << lhsSrc.attributes.test(Attribute::Target) << "\n";
-             llvm::dbgs() << "  rhs: " << rhs << "\n";
-             llvm::dbgs() << "  rhsSrc: " << rhsSrc << "\n";
-             llvm::dbgs() << "  rhsSrc kind: " << EnumToString(rhsSrc.kind) << "\n";
-             llvm::dbgs() << "  rhsSrc pointer: " << rhsSrc.attributes.test(Attribute::Pointer) << "\n";
-             llvm::dbgs() << "  rhsSrc target: " << rhsSrc.attributes.test(Attribute::Target) << "\n";
-             llvm::dbgs() << "\n";);
+  LLVM_DEBUG(
+      llvm::dbgs() << "AliasAnalysis::alias\n";
+      llvm::dbgs() << "  lhs: " << lhs << "\n";
+      llvm::dbgs() << "  lhsSrc: " << lhsSrc << "\n";
+      llvm::dbgs() << "  lhsSrc kind: " << EnumToString(lhsSrc.kind) << "\n";
+      llvm::dbgs() << "  lhsSrc pointer: "
+                   << lhsSrc.attributes.test(Attribute::Pointer) << "\n";
+      llvm::dbgs() << "  lhsSrc target: "
+                   << lhsSrc.attributes.test(Attribute::Target) << "\n";
+      llvm::dbgs() << "  rhs: " << rhs << "\n";
+      llvm::dbgs() << "  rhsSrc: " << rhsSrc << "\n";
+      llvm::dbgs() << "  rhsSrc kind: " << EnumToString(rhsSrc.kind) << "\n";
+      llvm::dbgs() << "  rhsSrc pointer: "
+                   << rhsSrc.attributes.test(Attribute::Pointer) << "\n";
+      llvm::dbgs() << "  rhsSrc target: "
+                   << rhsSrc.attributes.test(Attribute::Target) << "\n";
+      llvm::dbgs() << "\n";);
 
   // Indirect case currently not handled. Conservatively assume
   // it aliases with everything

>From 75e2a26ec2469efb0274e8649daab6882de4ffc3 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Tue, 16 Apr 2024 17:12:51 -0400
Subject: [PATCH 4/5] Improve dummy argument identification

Make sure they're not block arguments not on functions.  Encapsulate
the check.
---
 .../flang/Optimizer/Analysis/AliasAnalysis.h  |  3 ++
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  | 17 +++++----
 .../lib/Optimizer/Transforms/AddAliasTags.cpp | 37 ++++++++-----------
 3 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index dd4eb363cc7277..80c52fe01a33c1 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -93,6 +93,9 @@ struct AliasAnalysis {
 
   /// Return the memory source of a value.
   Source getSource(mlir::Value);
+
+  /// Return true if `v` is a dummy argument.
+  static bool isDummyArgument(mlir::Value v);
 };
 
 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index f6a4795feb58bc..aba7e542cc960e 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -28,14 +28,6 @@ using namespace mlir;
 // AliasAnalysis: alias
 //===----------------------------------------------------------------------===//
 
-static bool isDummyArgument(mlir::Value v) {
-  auto blockArg{v.dyn_cast<mlir::BlockArgument>()};
-  if (!blockArg)
-    return false;
-
-  return blockArg.getOwner()->isEntryBlock();
-}
-
 /// Temporary function to skip through all the no op operations
 /// TODO: Generalize support of fir.load
 static mlir::Value getOriginalDef(mlir::Value v) {
@@ -429,4 +421,13 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
   return {v, type, ty, attributes, approximateSource};
 }
 
+bool AliasAnalysis::isDummyArgument(mlir::Value v) {
+  auto blockArg{v.dyn_cast<mlir::BlockArgument>()};
+  if (!blockArg)
+    return false;
+  auto *owner{blockArg.getOwner()};
+  return owner->isEntryBlock() &&
+         mlir::isa<mlir::FunctionOpInterface>(owner->getParentOp());
+}
+
 } // namespace fir
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 5c6d3e47492762..8babd28564dd3d 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -170,29 +170,24 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
       LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to direct " << name
                                         << " at " << *op << "\n");
       tag = state.getFuncTree(func).directDataTree.getTag(name);
-    } else {
-      bool sourceIsDummyArgument = false;
-      if (auto blockArg =
-              source.u.get<mlir::Value>().dyn_cast<mlir::BlockArgument>())
-        sourceIsDummyArgument = blockArg.getOwner()->isEntryBlock();
-      if (sourceIsDummyArgument) {
-        std::string name = getFuncArgName(source.u.get<mlir::Value>());
-        if (!name.empty()) {
-          LLVM_DEBUG(llvm::dbgs().indent(2)
-                     << "Found reference to direct from dummy argument " << name
-                     << " at " << *op << "\n");
-          tag = state.getFuncTree(func).directDataTree.getTag(name);
-        } else {
-          LLVM_DEBUG(llvm::dbgs().indent(2)
-                     << "WARN: for direct, couldn't find a name for dummy "
-                     << "argument " << *op << "\n");
-        }
+    } else if (fir::AliasAnalysis::isDummyArgument(
+                   source.u.get<mlir::Value>())) {
+      std::string name = getFuncArgName(source.u.get<mlir::Value>());
+      if (!name.empty()) {
+        LLVM_DEBUG(llvm::dbgs().indent(2)
+                   << "Found reference to direct from dummy argument " << name
+                   << " at " << *op << "\n");
+        tag = state.getFuncTree(func).directDataTree.getTag(name);
       } else {
-        // SourceKind::Direct is likely to be extended to more cases in the
-        // future
-        LLVM_DEBUG(llvm::dbgs().indent(2) << "Can't get name for direct "
-                                          << source << " at " << *op << "\n");
+        LLVM_DEBUG(llvm::dbgs().indent(2)
+                   << "WARN: for direct, couldn't find a name for dummy "
+                   << "argument " << *op << "\n");
       }
+    } else {
+      // SourceKind::Direct is likely to be extended to more cases in the
+      // future
+      LLVM_DEBUG(llvm::dbgs().indent(2) << "Can't get name for direct "
+                                        << source << " at " << *op << "\n");
     }
 
     // TBAA for local allocations

>From ca7a18b5db6f74b5857fc7276d5d474996961f79 Mon Sep 17 00:00:00 2001
From: "Joel E. Denny" <jdenny.ornl at gmail.com>
Date: Thu, 18 Apr 2024 13:48:08 -0400
Subject: [PATCH 5/5] Rename a symbol in a test for consistency

---
 .../AliasAnalysis/alias-analysis-box-addr-load/arg.fir        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
index b97a712360124a..36eaf3a1576288 100644
--- a/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
+++ b/flang/test/Analysis/AliasAnalysis/alias-analysis-box-addr-load/arg.fir
@@ -53,10 +53,10 @@
 
 // The address *in* an allocatable cannot alias the address *of* that
 // allocatable.
-// CHECK-DAG: alloc#0 <-> alloc.tgt_addr#0: NoAlias
+// CHECK-DAG: alloc.addr#0 <-> alloc.tgt_addr#0: NoAlias
 
 func.func @_QPtest(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p0"}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg2: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "arr"}, %arg3: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "t_arr", fir.target}, %arg4: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "alloc"}, %arg5: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "t_alloc", fir.target}) attributes {test.ptr="func"} {
-  %0:2 = hlfir.declare %arg4 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEalloc", test.ptr="alloc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
+  %0:2 = hlfir.declare %arg4 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtestEalloc", test.ptr="alloc.addr"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
   %1:2 = hlfir.declare %arg2 {uniq_name = "_QFtestEarr"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
   %2:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp0"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)
   %3:2 = hlfir.declare %arg1 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtestEp1"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>)



More information about the flang-commits mailing list