[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