[flang-commits] [flang] [flang] Restructured TBAA trees in AddAliasTags pass. (PR #136725)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Wed Apr 23 12:53:34 PDT 2025
https://github.com/vzakhari updated https://github.com/llvm/llvm-project/pull/136725
>From 75b83fb0f9c3e740e1296ec2ef7425c1391a729d Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Mon, 21 Apr 2025 09:01:05 -0700
Subject: [PATCH 1/2] [flang] Restructured TBAA trees in AddAliasTags pass.
This patch produces the following TBAA tree for a function:
Function root
|
"any access"
|
|- "descriptor member"
|- "any data access"
|
|- "dummy arg data"
|- "target data"
|
|- "allocated data"
|- "direct data"
|- "global data"
The TBAA tags are assigned using the following logic:
* All POINTER variables point to the root of "target data".
* Dummy arguments without POINTER/TARGET point to their
leafs under "dummy arg data".
* Dummy arguments with TARGET point to the root of "target data".
* Global variables without descriptors point to their leafs under
"global data" (including the ones with TARGET).
* Global variables with descriptors point to their leafs under
"direct data" (including the ones with TARGET).
* Locally allocated variables point to their leafs under
"allocated data" (including the ones with TARGET).
This change makes it possible to disambiguate globals like:
module data
real, allocatable :: a(:)
real, allocatable, target :: b(:)
end
Indeed, two direct references to global vars cannot alias
even if any/both of them have TARGET attribute.
In addition, the dummy arguments without POINTER/TARGET cannot alias
any other variable even with POINTER/TARGET. This was not expressed
in TBAA before this change.
As before, any "unknown" memory references (such as with Indirect
source, as classified by FIR alias analysis) may alias with
anything, as long as they point to the root of "any access".
Please think of the counterexamples for which this structure
may not work.
---
.../flang/Optimizer/Analysis/AliasAnalysis.h | 6 +
.../flang/Optimizer/Analysis/TBAAForest.h | 35 +-
.../lib/Optimizer/Analysis/AliasAnalysis.cpp | 8 +
flang/lib/Optimizer/Analysis/TBAAForest.cpp | 17 +-
.../lib/Optimizer/Transforms/AddAliasTags.cpp | 51 ++-
.../test/Transforms/tbaa-with-dummy-scope.fir | 171 +++------
.../Transforms/tbaa-with-dummy-scope2.fir | 10 +-
flang/test/Transforms/tbaa.fir | 12 +-
flang/test/Transforms/tbaa2.fir | 19 +-
flang/test/Transforms/tbaa3.fir | 331 ++++++++++++++++++
10 files changed, 489 insertions(+), 171 deletions(-)
create mode 100644 flang/test/Transforms/tbaa3.fir
diff --git a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
index c71988d081dd0..30dd5f754d0b5 100644
--- a/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
+++ b/flang/include/flang/Optimizer/Analysis/AliasAnalysis.h
@@ -155,6 +155,12 @@ struct AliasAnalysis {
/// Return true, if Target or Pointer attribute is set.
bool isTargetOrPointer() const;
+ /// Return true, if Target attribute is set.
+ bool isTarget() const;
+
+ /// Return true, if Pointer attribute is set.
+ bool isPointer() const;
+
bool isDummyArgument() const;
bool isData() const;
bool isBoxData() const;
diff --git a/flang/include/flang/Optimizer/Analysis/TBAAForest.h b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
index f95fcffd96e93..4d2281642b43d 100644
--- a/flang/include/flang/Optimizer/Analysis/TBAAForest.h
+++ b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
@@ -40,6 +40,12 @@ struct TBAATree {
mlir::LLVM::TBAATagAttr getTag(llvm::StringRef uniqueId) const;
+ /// Create a TBAA tag pointing to the root of this subtree,
+ /// i.e. all the children tags will alias with this tag.
+ mlir::LLVM::TBAATagAttr getTag() const;
+
+ mlir::LLVM::TBAATypeDescriptorAttr getRoot() const { return parent; }
+
private:
SubtreeState(mlir::MLIRContext *ctx, std::string name,
mlir::LLVM::TBAANodeAttr grandParent)
@@ -51,17 +57,44 @@ struct TBAATree {
const std::string parentId;
mlir::MLIRContext *const context;
mlir::LLVM::TBAATypeDescriptorAttr parent;
- llvm::DenseMap<llvm::StringRef, mlir::LLVM::TBAATagAttr> tagDedup;
};
+ /// A subtree for POINTER/TARGET variables data.
+ /// Any POINTER variable must use a tag that points
+ /// to the root of this subtree.
+ /// A TARGET dummy argument must also point to this root.
+ SubtreeState targetDataTree;
+ /// A subtree for global variables data (e.g. user module variables).
SubtreeState globalDataTree;
+ /// A subtree for variables allocated via fir.alloca or fir.allocmem.
SubtreeState allocatedDataTree;
+ /// A subtree for subprogram's dummy arguments.
+ /// It only contains children for the dummy arguments
+ /// that are not POINTER/TARGET. They all do not conflict
+ /// with each other and with any other data access, except
+ /// with unknown data accesses (FIR alias analysis uses
+ /// SourceKind::Indirect for sources of such accesses).
SubtreeState dummyArgDataTree;
+ /// A subtree for global variables descriptors.
SubtreeState directDataTree;
mlir::LLVM::TBAATypeDescriptorAttr anyAccessDesc;
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc;
mlir::LLVM::TBAATypeDescriptorAttr anyDataTypeDesc;
+ // Structure of the created tree:
+ // Function root
+ // |
+ // "any access"
+ // |
+ // |- "descriptor member"
+ // |- "any data access"
+ // |
+ // |- "dummy arg data"
+ // |- "target data"
+ // |
+ // |- "allocated data"
+ // |- "direct data"
+ // |- "global data"
static TBAATree buildTree(mlir::StringAttr functionName);
private:
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index bda98871a1c7a..cbfc8b63ab64d 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -110,6 +110,14 @@ bool AliasAnalysis::Source::isTargetOrPointer() const {
attributes.test(Attribute::Target);
}
+bool AliasAnalysis::Source::isTarget() const {
+ return attributes.test(Attribute::Target);
+}
+
+bool AliasAnalysis::Source::isPointer() const {
+ return attributes.test(Attribute::Pointer);
+}
+
bool AliasAnalysis::Source::isDummyArgument() const {
if (auto v = origin.u.dyn_cast<mlir::Value>()) {
return fir::isDummyArgument(v);
diff --git a/flang/lib/Optimizer/Analysis/TBAAForest.cpp b/flang/lib/Optimizer/Analysis/TBAAForest.cpp
index 786c4932ea89e..cce50e0de1bc7 100644
--- a/flang/lib/Optimizer/Analysis/TBAAForest.cpp
+++ b/flang/lib/Optimizer/Analysis/TBAAForest.cpp
@@ -11,9 +11,6 @@
mlir::LLVM::TBAATagAttr
fir::TBAATree::SubtreeState::getTag(llvm::StringRef uniqueName) const {
- // mlir::LLVM::TBAATagAttr &tag = tagDedup[uniqueName];
- // if (tag)
- // return tag;
std::string id = (parentId + "/" + uniqueName).str();
mlir::LLVM::TBAATypeDescriptorAttr type =
mlir::LLVM::TBAATypeDescriptorAttr::get(
@@ -22,6 +19,10 @@ fir::TBAATree::SubtreeState::getTag(llvm::StringRef uniqueName) const {
// return tag;
}
+mlir::LLVM::TBAATagAttr fir::TBAATree::SubtreeState::getTag() const {
+ return mlir::LLVM::TBAATagAttr::get(parent, parent, 0);
+}
+
fir::TBAATree fir::TBAATree::buildTree(mlir::StringAttr func) {
llvm::StringRef funcName = func.getValue();
std::string rootId = ("Flang function root " + funcName).str();
@@ -53,9 +54,13 @@ fir::TBAATree fir::TBAATree::buildTree(mlir::StringAttr func) {
fir::TBAATree::TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess,
mlir::LLVM::TBAATypeDescriptorAttr dataRoot,
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc)
- : globalDataTree(dataRoot.getContext(), "global data", dataRoot),
- allocatedDataTree(dataRoot.getContext(), "allocated data", dataRoot),
+ : targetDataTree(dataRoot.getContext(), "target data", dataRoot),
+ globalDataTree(dataRoot.getContext(), "global data",
+ targetDataTree.getRoot()),
+ allocatedDataTree(dataRoot.getContext(), "allocated data",
+ targetDataTree.getRoot()),
dummyArgDataTree(dataRoot.getContext(), "dummy arg data", dataRoot),
- directDataTree(dataRoot.getContext(), "direct data", dataRoot),
+ directDataTree(dataRoot.getContext(), "direct data",
+ targetDataTree.getRoot()),
anyAccessDesc(anyAccess), boxMemberTypeDesc(boxMemberTypeDesc),
anyDataTypeDesc(dataRoot) {}
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index e6fc2ed992e38..66b4b84998801 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -198,12 +198,6 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs() << "Analysing " << op << "\n");
const fir::AliasAnalysis::Source &source = state.getSource(memref);
- if (source.isTargetOrPointer()) {
- LLVM_DEBUG(llvm::dbgs().indent(2) << "Skipping TARGET/POINTER\n");
- // These will get an "any data access" tag in TBAABuilder (CodeGen): causing
- // them to "MayAlias" with all non-box accesses
- return;
- }
// Process the scopes, if not processed yet.
state.processFunctionScopes(func);
@@ -228,15 +222,21 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to dummy argument at " << *op << "\n");
std::string name = getFuncArgName(llvm::cast<mlir::Value>(source.origin.u));
- if (!name.empty())
+ // If it is a TARGET or POINTER, then we do not care about the name,
+ // because the tag points to the root of the subtree currently.
+ if (source.isTargetOrPointer()) {
+ tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ } else if (!name.empty()) {
tag = state.getFuncTreeWithScope(func, scopeOp)
.dummyArgDataTree.getTag(name);
- else
+ } else {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "WARN: couldn't find a name for dummy argument " << *op
<< "\n");
+ tag = state.getFuncTreeWithScope(func, scopeOp).dummyArgDataTree.getTag();
+ }
- // TBAA for global variables
+ // TBAA for global variables without descriptors
} else if (enableGlobals &&
source.kind == fir::AliasAnalysis::SourceKind::Global &&
!source.isBoxData()) {
@@ -244,9 +244,13 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
const char *name = glbl.getRootReference().data();
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to global " << name
<< " at " << *op << "\n");
- tag = state.getFuncTreeWithScope(func, scopeOp).globalDataTree.getTag(name);
+ if (source.isPointer())
+ tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ else
+ tag =
+ state.getFuncTreeWithScope(func, scopeOp).globalDataTree.getTag(name);
- // TBAA for SourceKind::Direct
+ // TBAA for global variables with descriptors
} else if (enableDirect &&
source.kind == fir::AliasAnalysis::SourceKind::Global &&
source.isBoxData()) {
@@ -254,11 +258,12 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
const char *name = glbl.getRootReference().data();
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to direct " << name
<< " at " << *op << "\n");
- tag =
- state.getFuncTreeWithScope(func, scopeOp).directDataTree.getTag(name);
+ if (source.isPointer())
+ tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ else
+ tag = state.getFuncTreeWithScope(func, scopeOp)
+ .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");
}
@@ -269,11 +274,23 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
std::optional<llvm::StringRef> name;
mlir::Operation *sourceOp =
llvm::cast<mlir::Value>(source.origin.u).getDefiningOp();
+ bool unknownAllocOp = false;
if (auto alloc = mlir::dyn_cast_or_null<fir::AllocaOp>(sourceOp))
name = alloc.getUniqName();
else if (auto alloc = mlir::dyn_cast_or_null<fir::AllocMemOp>(sourceOp))
name = alloc.getUniqName();
- if (name) {
+ else
+ unknownAllocOp = true;
+
+ if (unknownAllocOp) {
+ LLVM_DEBUG(llvm::dbgs().indent(2)
+ << "WARN: unknown defining op for SourceKind::Allocate " << *op
+ << "\n");
+ } else if (source.isPointer()) {
+ LLVM_DEBUG(llvm::dbgs().indent(2)
+ << "Found reference to allocation at " << *op << "\n");
+ tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ } else if (name) {
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation "
<< name << " at " << *op << "\n");
tag = state.getFuncTreeWithScope(func, scopeOp)
@@ -282,6 +299,8 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "WARN: couldn't find a name for allocation " << *op
<< "\n");
+ tag =
+ state.getFuncTreeWithScope(func, scopeOp).allocatedDataTree.getTag();
}
} else {
if (source.kind != fir::AliasAnalysis::SourceKind::Argument &&
diff --git a/flang/test/Transforms/tbaa-with-dummy-scope.fir b/flang/test/Transforms/tbaa-with-dummy-scope.fir
index 738692814cde5..7624de9431e08 100644
--- a/flang/test/Transforms/tbaa-with-dummy-scope.fir
+++ b/flang/test/Transforms/tbaa-with-dummy-scope.fir
@@ -2,7 +2,7 @@
// subroutine test(x, y)
// real, target :: x, y
-// x = y ! the load/store do not have TBAA due to TARGET
+// x = y
// call inner(x, y) ! the inlined load/store go to Scope 1
// call inner(x, y) ! the inlined load/store go to Scope 2
// contains
@@ -12,25 +12,30 @@
// end subroutine inner
// end subroutine test
+// CHECK: #[[TEST1ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root test1">
// CHECK: #[[$ATTR_0:.+]] = #llvm.tbaa_root<id = "Flang function root test1 - Scope 1">
// CHECK: #[[$ATTR_1:.+]] = #llvm.tbaa_root<id = "Flang function root test1 - Scope 2">
-// CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root, 0>}>
-// CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root1, 0>}>
-// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc, 0>}>
-// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc1, 0>}>
-// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#tbaa_type_desc3, 0>}>
-// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEy", members = {<#tbaa_type_desc4, 0>}>
-// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEx", members = {<#tbaa_type_desc4, 0>}>
-// CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEy", members = {<#tbaa_type_desc5, 0>}>
-// CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEx", members = {<#tbaa_type_desc5, 0>}>
-// CHECK: #[[$ATTR_12:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc6, access_type = #tbaa_type_desc6, offset = 0>
-// CHECK: #[[$ATTR_13:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc7, access_type = #tbaa_type_desc7, offset = 0>
-// CHECK: #[[$ATTR_14:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc8, access_type = #tbaa_type_desc8, offset = 0>
-// CHECK: #[[$ATTR_15:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc9, access_type = #tbaa_type_desc9, offset = 0>
+// CHECK: #[[TEST1ANYACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[TEST1ROOT]], 0>}>
+// CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[$ATTR_0]], 0>}>
+// CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[$ATTR_1]], 0>}>
+// CHECK: #[[TEST1ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[TEST1ANYACCESS]], 0>}>
+// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_2]], 0>}>
+// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_3]], 0>}>
+// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[TEST1ANYDATA]], 0>}>
+// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[$ATTR_4]], 0>}>
+// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[$ATTR_5]], 0>}>
+// CHECK: #[[TARGETTAG:.+]] = #llvm.tbaa_tag<base_type = #[[TARGETDATA]], access_type = #[[TARGETDATA]], offset = 0>
+// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEy", members = {<#[[$ATTR_6]], 0>}>
+// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEx", members = {<#[[$ATTR_6]], 0>}>
+// CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEy", members = {<#[[$ATTR_7]], 0>}>
+// CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestFinnerEx", members = {<#[[$ATTR_7]], 0>}>
+// CHECK: #[[$ATTR_12:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_8]], access_type = #[[$ATTR_8]], offset = 0>
+// CHECK: #[[$ATTR_13:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_9]], access_type = #[[$ATTR_9]], offset = 0>
+// CHECK: #[[$ATTR_14:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_10]], access_type = #[[$ATTR_10]], offset = 0>
+// CHECK: #[[$ATTR_15:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_11]], access_type = #[[$ATTR_11]], offset = 0>
// CHECK: func.func @test1(
-// CHECK: %[[VAL_5:.*]] = fir.load %{{.*}} : !fir.ref<f32>
-// CHECK: fir.store %{{.*}} : !fir.ref<f32>
+// CHECK: %[[VAL_5:.*]] = fir.load %{{.*}} {tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+// CHECK: fir.store %{{.*}} {tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
// CHECK: %[[VAL_6:.*]] = fir.dummy_scope : !fir.dscope
// CHECK: %[[VAL_9:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_12]]]} : !fir.ref<f32>
// CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_13]]]} : !fir.ref<f32>
@@ -58,102 +63,6 @@ func.func @test1(%arg0: !fir.ref<f32> {fir.bindc_name = "x", fir.target}, %arg1:
// -----
-// Check that without proper fir.dummy_scope placement
-// we just put everything into the root scope.
-
-// CHECK: #[[$ATTR_16:.+]] = #llvm.tbaa_root<id = "Flang function root test2">
-// CHECK: #[[$ATTR_17:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root, 0>}>
-// CHECK: #[[$ATTR_18:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc, 0>}>
-// CHECK: #[[$ATTR_19:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#tbaa_type_desc1, 0>}>
-// CHECK: #[[$ATTR_20:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestEy", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_21:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtestEx", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_22:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc3, access_type = #tbaa_type_desc3, offset = 0>
-// CHECK: #[[$ATTR_23:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc4, access_type = #tbaa_type_desc4, offset = 0>
-// CHECK: func.func @test2(
-// CHECK: %[[VAL_4:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_22]]]} : !fir.ref<f32>
-// CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_23]]]} : !fir.ref<f32>
-// CHECK: %[[VAL_5:.*]] = fir.declare
-// CHECK: %[[VAL_6:.*]] = fir.declare
-// CHECK: %[[VAL_7:.*]] = fir.load %{{.*}} {tbaa = [#[[$ATTR_22]]]} : !fir.ref<f32>
-// CHECK: fir.store %{{.*}} {tbaa = [#[[$ATTR_23]]]} : !fir.ref<f32>
-func.func @test2(%arg0: !fir.ref<f32> {fir.bindc_name = "x"}, %arg1: !fir.ref<f32> {fir.bindc_name = "y"}) {
- %0 = fir.declare %arg0 {uniq_name = "_QFtestEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %1 = fir.declare %arg1 {uniq_name = "_QFtestEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %2 = fir.load %1 : !fir.ref<f32>
- fir.store %2 to %0 : !fir.ref<f32>
- %3 = fir.declare %0 {uniq_name = "_QFtestFinnerEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %4 = fir.declare %1 {uniq_name = "_QFtestFinnerEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %5 = fir.load %4 : !fir.ref<f32>
- fir.store %5 to %3 : !fir.ref<f32>
- return
-}
-
-// -----
-
-// module test
-// real :: x, y
-// contains
-// subroutine caller
-// x = y ! the load/store go to the root scope
-// call callee
-// end subroutine caller
-// subroutine callee
-// x = y ! the load/store go to the root scope
-// ! Since there are no dummy arguments in callee,
-// ! it is better to put the load/store into the
-// ! enclosing root scope, so that they can be
-// ! disambiguated using TBAA with the loads/stores
-// ! in the enclosing scope.
-// end subroutine callee
-// end module test
-
-// CHECK: #[[$ATTR_24:.+]] = #llvm.tbaa_root<id = "Flang function root _QMtestPcaller">
-// CHECK: #[[$ATTR_25:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root, 0>}>
-// CHECK: #[[$ATTR_26:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc, 0>}>
-// CHECK: #[[$ATTR_27:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#tbaa_type_desc1, 0>}>
-// CHECK: #[[$ATTR_28:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEy", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_29:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEx", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_30:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc3, access_type = #tbaa_type_desc3, offset = 0>
-// CHECK: #[[$ATTR_31:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc4, access_type = #tbaa_type_desc4, offset = 0>
-// CHECK: func.func @_QMtestPcaller() {
-// CHECK: %[[VAL_0:.*]] = fir.address_of(@_QMtestEx) : !fir.ref<f32>
-// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "_QMtestEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
-// CHECK: %[[VAL_2:.*]] = fir.address_of(@_QMtestEy) : !fir.ref<f32>
-// CHECK: %[[VAL_3:.*]] = fir.declare %[[VAL_2]] {uniq_name = "_QMtestEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
-// CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] {tbaa = [#[[$ATTR_30]]]} : !fir.ref<f32>
-// CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] {tbaa = [#[[$ATTR_31]]]} : !fir.ref<f32>
-// CHECK: %[[VAL_5:.*]] = fir.address_of(@_QMtestEx) : !fir.ref<f32>
-// CHECK: %[[VAL_6:.*]] = fir.declare %[[VAL_5]] {uniq_name = "_QMtestEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
-// CHECK: %[[VAL_7:.*]] = fir.address_of(@_QMtestEy) : !fir.ref<f32>
-// CHECK: %[[VAL_8:.*]] = fir.declare %[[VAL_7]] {uniq_name = "_QMtestEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
-// CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] {tbaa = [#[[$ATTR_30]]]} : !fir.ref<f32>
-// CHECK: fir.store %[[VAL_9]] to %[[VAL_6]] {tbaa = [#[[$ATTR_31]]]} : !fir.ref<f32>
-func.func @_QMtestPcaller() {
- %0 = fir.address_of(@_QMtestEx) : !fir.ref<f32>
- %1 = fir.declare %0 {uniq_name = "_QMtestEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %2 = fir.address_of(@_QMtestEy) : !fir.ref<f32>
- %3 = fir.declare %2 {uniq_name = "_QMtestEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %4 = fir.load %3 : !fir.ref<f32>
- fir.store %4 to %1 : !fir.ref<f32>
- %5 = fir.address_of(@_QMtestEx) : !fir.ref<f32>
- %6 = fir.declare %5 {uniq_name = "_QMtestEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %7 = fir.address_of(@_QMtestEy) : !fir.ref<f32>
- %8 = fir.declare %7 {uniq_name = "_QMtestEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
- %9 = fir.load %8 : !fir.ref<f32>
- fir.store %9 to %6 : !fir.ref<f32>
- return
-}
-fir.global @_QMtestEx : f32 {
- %0 = fir.zero_bits f32
- fir.has_value %0 : f32
-}
-fir.global @_QMtestEy : f32 {
- %0 = fir.zero_bits f32
- fir.has_value %0 : f32
-}
-
-// -----
-
// module test
// real :: x, y
// contains
@@ -170,23 +79,25 @@ fir.global @_QMtestEy : f32 {
// CHECK: #[[$ATTR_32:.+]] = #llvm.tbaa_root<id = "Flang function root _QMtestPcaller">
// CHECK: #[[$ATTR_33:.+]] = #llvm.tbaa_root<id = "Flang function root _QMtestPcaller - Scope 1">
-// CHECK: #[[$ATTR_34:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root, 0>}>
-// CHECK: #[[$ATTR_35:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#tbaa_root1, 0>}>
-// CHECK: #[[$ATTR_36:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc, 0>}>
-// CHECK: #[[$ATTR_37:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#tbaa_type_desc1, 0>}>
-// CHECK: #[[$ATTR_38:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#tbaa_type_desc2, 0>}>
-// CHECK: #[[$ATTR_39:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#tbaa_type_desc3, 0>}>
-// CHECK: #[[$ATTR_40:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#tbaa_type_desc3, 0>}>
-// CHECK: #[[$ATTR_41:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEy", members = {<#tbaa_type_desc4, 0>}>
-// CHECK: #[[$ATTR_42:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEx", members = {<#tbaa_type_desc4, 0>}>
-// CHECK: #[[$ATTR_43:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEy", members = {<#tbaa_type_desc5, 0>}>
-// CHECK: #[[$ATTR_44:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEx", members = {<#tbaa_type_desc5, 0>}>
-// CHECK: #[[$ATTR_45:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMtestFcalleeEz", members = {<#tbaa_type_desc6, 0>}>
-// CHECK: #[[$ATTR_46:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc7, access_type = #tbaa_type_desc7, offset = 0>
-// CHECK: #[[$ATTR_47:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc8, access_type = #tbaa_type_desc8, offset = 0>
-// CHECK: #[[$ATTR_48:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc9, access_type = #tbaa_type_desc9, offset = 0>
-// CHECK: #[[$ATTR_49:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc10, access_type = #tbaa_type_desc10, offset = 0>
-// CHECK: #[[$ATTR_50:.+]] = #llvm.tbaa_tag<base_type = #tbaa_type_desc11, access_type = #tbaa_type_desc11, offset = 0>
+// CHECK: #[[$ATTR_34:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[$ATTR_32]], 0>}>
+// CHECK: #[[$ATTR_35:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[$ATTR_33]], 0>}>
+// CHECK: #[[$ATTR_36:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_34]], 0>}>
+// CHECK: #[[$ATTR_37:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_35]], 0>}>
+// CHECK: #[[CALLERTARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[$ATTR_36]], 0>}>
+// CHECK: #[[CALLEETARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[$ATTR_37]], 0>}>
+// CHECK: #[[$ATTR_40:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[$ATTR_37]], 0>}>
+// CHECK: #[[$ATTR_38:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[CALLERTARGETDATA]], 0>}>
+// CHECK: #[[$ATTR_39:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[CALLEETARGETDATA]], 0>}>
+// CHECK: #[[$ATTR_45:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMtestFcalleeEz", members = {<#[[$ATTR_40]], 0>}>
+// CHECK: #[[$ATTR_50:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_45]], access_type = #[[$ATTR_45]], offset = 0>
+// CHECK: #[[$ATTR_41:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEy", members = {<#[[$ATTR_38]], 0>}>
+// CHECK: #[[$ATTR_42:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEx", members = {<#[[$ATTR_38]], 0>}>
+// CHECK: #[[$ATTR_43:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEy", members = {<#[[$ATTR_39]], 0>}>
+// CHECK: #[[$ATTR_44:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMtestEx", members = {<#[[$ATTR_39]], 0>}>
+// CHECK: #[[$ATTR_46:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_41]], access_type = #[[$ATTR_41]], offset = 0>
+// CHECK: #[[$ATTR_47:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_42]], access_type = #[[$ATTR_42]], offset = 0>
+// CHECK: #[[$ATTR_48:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_43]], access_type = #[[$ATTR_43]], offset = 0>
+// CHECK: #[[$ATTR_49:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_44]], access_type = #[[$ATTR_44]], offset = 0>
// CHECK: func.func @_QMtestPcaller(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "z"}) {
// CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
diff --git a/flang/test/Transforms/tbaa-with-dummy-scope2.fir b/flang/test/Transforms/tbaa-with-dummy-scope2.fir
index a28b4d56f442c..c8f419fbee652 100644
--- a/flang/test/Transforms/tbaa-with-dummy-scope2.fir
+++ b/flang/test/Transforms/tbaa-with-dummy-scope2.fir
@@ -44,10 +44,11 @@ func.func @_QPtest1() attributes {noinline} {
// CHECK: #[[$ATTR_1:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[$ATTR_0]], 0>}>
// CHECK: #[[$ATTR_2:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_1]], 0>}>
// CHECK: #[[$ATTR_3:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[$ATTR_2]], 0>}>
-// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[$ATTR_2]], 0>}>
+// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[$ATTR_2]], 0>}>
// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtest1FinnerEx", members = {<#[[$ATTR_3]], 0>}>
-// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmEglob", members = {<#[[$ATTR_4]], 0>}>
+// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_5]], access_type = #[[$ATTR_5]], offset = 0>
+// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmEglob", members = {<#[[$ATTR_4]], 0>}>
// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_6]], access_type = #[[$ATTR_6]], offset = 0>
// CHECK-LABEL: func.func @_QPtest1() attributes {noinline} {
// CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtest1FinnerEy"}
@@ -87,10 +88,11 @@ func.func @_QPtest2() attributes {noinline} {
// CHECK: #[[$ATTR_4:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_2]], 0>}>
// CHECK: #[[$ATTR_5:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[$ATTR_3]], 0>}>
// CHECK: #[[$ATTR_6:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[$ATTR_4]], 0>}>
-// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[$ATTR_5]], 0>}>
+// CHECK: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[$ATTR_5]], 0>}>
// CHECK: #[[$ATTR_8:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtest2FinnerEx", members = {<#[[$ATTR_6]], 0>}>
-// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmEglob", members = {<#[[$ATTR_7]], 0>}>
+// CHECK: #[[$ATTR_7:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
// CHECK: #[[$ATTR_10:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_8]], access_type = #[[$ATTR_8]], offset = 0>
+// CHECK: #[[$ATTR_9:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmEglob", members = {<#[[$ATTR_7]], 0>}>
// CHECK: #[[$ATTR_11:.+]] = #llvm.tbaa_tag<base_type = #[[$ATTR_9]], access_type = #[[$ATTR_9]], offset = 0>
// CHECK-LABEL: func.func @_QPtest2() attributes {noinline} {
// CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtest2FinnerEy"}
diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir
index f8e16b174e9c7..88e200f43b4ef 100644
--- a/flang/test/Transforms/tbaa.fir
+++ b/flang/test/Transforms/tbaa.fir
@@ -108,9 +108,10 @@
// CHECK: #[[TARGET_ANY_ACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[TARGET_ROOT]], 0>}>
// CHECK: #[[TARGET_ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[TARGET_ANY_ACCESS]], 0>}>
// CHECK: #[[TARGET_ANY_ARG:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[TARGET_ANY_DATA]], 0>}>
+// CHECK: #[[TARGET_TARGET_DATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[TARGET_ANY_DATA]], 0>}>
+// CHECK: #[[TARGET_A_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[TARGET_TARGET_DATA]], access_type = #[[TARGET_TARGET_DATA]], offset = 0>
// CHECK: #[[TARGET_B:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtargetargEb", members = {<#[[TARGET_ANY_ARG]], 0>}>
// CHECK: #[[TARGET_B_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[TARGET_B]], access_type = #[[TARGET_B]], offset = 0>
-// No entry for "dummy arg data/a" because that pointer should get "any data access" becase it has the TARGET attribute
// CHECK-LABEL: func.func @_QPtargetarg(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a", fir.target},
@@ -124,8 +125,7 @@
// CHECK: %[[VAL_7:.*]] = fir.array_coor %[[VAL_6]] %[[VAL_2]] : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
// CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] {tbaa = [#[[TARGET_B_TAG]]]} : !fir.ref<i32>
// CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_4]] %[[VAL_2]] : (!fir.box<!fir.array<?xi32>>, index) -> !fir.ref<i32>
-// "any data access" tag is added by TBAABuilder during CodeGen
-// CHECK: fir.store %[[VAL_8]] to %[[VAL_9]] : !fir.ref<i32>
+// CHECK: fir.store %[[VAL_8]] to %[[VAL_9]] {tbaa = [#[[TARGET_A_TAG]]]} : !fir.ref<i32>
// CHECK: return
// CHECK: }
@@ -157,9 +157,10 @@
// CHECK: #[[POINTER_ANY_ACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[POINTER_ROOT]], 0>}>
// CHECK: #[[POINTER_ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[POINTER_ANY_ACCESS]], 0>}>
// CHECK: #[[POINTER_ANY_ARG:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[POINTER_ANY_DATA]], 0>}>
+// CHECK: #[[POINTER_TARGET_DATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[POINTER_ANY_DATA]], 0>}>
+// CHECK: #[[POINTER_A_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[POINTER_TARGET_DATA]], access_type = #[[POINTER_TARGET_DATA]], offset = 0>
// CHECK: #[[POINTER_B:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFpointerargEb", members = {<#[[POINTER_ANY_ARG]], 0>}>
// CHECK: #[[POINTER_B_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[POINTER_B]], access_type = #[[POINTER_B]], offset = 0>
-// No entry for "dummy arg data/a" because that pointer should get "any data access" becase it has the POINTER attribute
// CHECK-LABEL: func.func @_QPpointerarg(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "a"},
@@ -177,8 +178,7 @@
// CHECK: %[[VAL_10:.*]]:3 = fir.box_dims %[[VAL_9]], %[[VAL_2]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, index) -> (index, index, index)
// CHECK: %[[VAL_11:.*]] = fir.shift %[[VAL_10]]#0 : (index) -> !fir.shift<1>
// CHECK: %[[VAL_12:.*]] = fir.array_coor %[[VAL_9]](%[[VAL_11]]) %[[VAL_3]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>, !fir.shift<1>, index) -> !fir.ref<i32>
-// "any data access" tag is added by TBAABuilder during CodeGen
-// CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] : !fir.ref<i32>
+// CHECK: fir.store %[[VAL_8]] to %[[VAL_12]] {tbaa = [#[[POINTER_A_TAG]]]} : !fir.ref<i32>
// CHECK: return
// CHECK: }
diff --git a/flang/test/Transforms/tbaa2.fir b/flang/test/Transforms/tbaa2.fir
index 5c2503d69a8be..4678a1cd4a686 100644
--- a/flang/test/Transforms/tbaa2.fir
+++ b/flang/test/Transforms/tbaa2.fir
@@ -47,32 +47,35 @@
// CHECK: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QMmodPcallee">
// 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: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target 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_GLBL:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
+// CHECK: #[[ARG_LOW:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeElow", members = {<#[[ANY_ARG]], 0>}>
+// CHECK: #[[ANY_DIRECT:.+]] = #llvm.tbaa_type_desc<id = "direct data", members = {<#[[TARGETDATA]], 0>}>
+// CHECK: #[[ARG_Z:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeEz", members = {<#[[ANY_ARG]], 0>}>
+// CHECK: #[[ARG_Y:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeEy", members = {<#[[ANY_ARG]], 0>}>
+
+// CHECK: #[[ARG_LOW_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_LOW]], access_type = #[[ARG_LOW]], offset = 0>
+// CHECK: #[[ARG_Z_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_Z]], access_type = #[[ARG_Z]], offset = 0>
+// CHECK: #[[ARG_Y_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_Y]], access_type = #[[ARG_Y]], offset = 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: #[[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>}>
// CHECK: #[[GLBL_DYINV:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMmodEdyinv", members = {<#[[ANY_GLBL]], 0>}>
-// CHECK: #[[ARG_Y:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QMmodFcalleeEy", members = {<#[[ANY_ARG]], 0>}>
// CHECK: #[[GLBL_ZSTART_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_ZSTART]], access_type = #[[GLBL_ZSTART]], offset = 0>
// CHECK: #[[GLBL_ZSTOP_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_ZSTOP]], access_type = #[[GLBL_ZSTOP]], offset = 0>
// CHECK: #[[GLBL_YSTART_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_YSTART]], access_type = #[[GLBL_YSTART]], offset = 0>
// CHECK: #[[GLBL_YSTOP_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_YSTOP]], access_type = #[[GLBL_YSTOP]], offset = 0>
// CHECK: #[[GLBL_XSTART_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_XSTART]], access_type = #[[GLBL_XSTART]], offset = 0>
-// CHECK: #[[ARG_LOW_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_LOW]], access_type = #[[ARG_LOW]], offset = 0>
// CHECK: #[[DIRECT_A_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[DIRECT_A]], access_type = #[[DIRECT_A]], offset = 0>
// CHECK: #[[DIRECT_B_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[DIRECT_B]], access_type = #[[DIRECT_B]], offset = 0>
-// CHECK: #[[ARG_Z_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_Z]], access_type = #[[ARG_Z]], offset = 0>
// CHECK: #[[GLBL_DYINV_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLBL_DYINV]], access_type = #[[GLBL_DYINV]], offset = 0>
-// CHECK: #[[ARG_Y_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ARG_Y]], access_type = #[[ARG_Y]], offset = 0>
func.func @_QMmodPcallee(%arg0: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "z"}, %arg1: !fir.box<!fir.array<?x?x?xf32>> {fir.bindc_name = "y"}, %arg2: !fir.ref<!fir.box<!fir.heap<!fir.array<?x?x?xf32>>>> {fir.bindc_name = "low"}) {
%c2 = arith.constant 2 : index
diff --git a/flang/test/Transforms/tbaa3.fir b/flang/test/Transforms/tbaa3.fir
new file mode 100644
index 0000000000000..4fb9a095279ea
--- /dev/null
+++ b/flang/test/Transforms/tbaa3.fir
@@ -0,0 +1,331 @@
+// RUN: fir-opt --fir-add-alias-tags %s | FileCheck --check-prefixes=ALL,DEFAULT %s
+// RUN: fir-opt --fir-add-alias-tags --local-alloc-tbaa %s | FileCheck --check-prefixes=ALL,LOCAL %s
+
+// Test AddAliasTagsPass creating sub-tree for TARGET/POINTER variables.
+
+// module data
+// real :: glob(10)
+// real, target :: globt(10)
+// real, allocatable :: globa(:)
+// real, allocatable, target :: globat(:)
+// real, pointer :: globp(:)
+// end module data
+// subroutine test1(dummyf, dummyft, dummyas, dummyast, dummya, dummyat, dummyp)
+// use data
+// real :: dummyf(10)
+// real, target :: dummyft(10)
+// real :: dummyas(:)
+// real, target :: dummyast(:)
+// real, allocatable :: dummya(:)
+// real, allocatable, target :: dummyat(:)
+// real, pointer :: dummyp(:)
+// real :: local(10)
+// real, target :: localt(10)
+// real, allocatable :: locala(:)
+// real, allocatable, target :: localat(:)
+// real, pointer :: localp(:)
+// glob(1) = 1.0
+// globt(1) = 1.0
+// globa(1) = 1.0
+// globat(1) = 1.0
+// globp(1) = 1.0
+// dummyf(1) = 1.0
+// dummyft(1) = 1.0
+// dummyas(1) = 1.0
+// dummyast(1) = 1.0
+// dummya(1) = 1.0
+// dummyat(1) = 1.0
+// dummyp(1) = 1.0
+// local(1) = 1.0
+// localt(1) = 1.0
+// locala(1) = 1.0
+// localat(1) = 1.0
+// localp(1) = 1.0
+// end subroutine test1
+
+// "Flang function root _QPtest1"
+// |
+// "any access"
+// |
+// |- "descriptor member"
+// |- "any data access"
+// |
+// |- "dummy arg data"
+// | |
+// | |- "dummy arg data/_QFtest1Edummyf"
+// | |- "dummy arg data/_QFtest1Edummyas"
+// | |- "dummy arg data/_QFtest1Edummya"
+// |
+// |- "target data" <- all pointers and taget dummys
+// |
+// |- "global data"
+// | |
+// | |- "global data/_QMdataEglob"
+// | |- "global data/_QMdataEglobt"
+// |
+// |- "direct data" - "direct data/_QMdataEgloba"
+// | |
+// | |- "direct data/_QMdataEgloba"
+// | |- "direct data/_QMdataEglobat"
+// |
+// |- "allocated data"
+// |
+// |- "allocated data/_QFtest1Elocal"
+// |- "allocated data/_QFtest1Elocalt"
+// |- "allocated data/_QFtest1Elocala"
+// |- "allocated data/_QFtest1Elocalat"
+
+// ALL: #[[FUNCROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest1">
+// ALL: #[[ANYACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[FUNCROOT]], 0>}>
+// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANYACCESS]], 0>}>
+// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA]], 0>}>
+// ALL: #[[DUMMYDATA:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[ANYDATA]], 0>}>
+// ALL: #[[TARGETTAG:.+]] = #llvm.tbaa_tag<base_type = #[[TARGETDATA]], access_type = #[[TARGETDATA]], offset = 0>
+// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[DIRECTDATA:.+]] = #llvm.tbaa_type_desc<id = "direct data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[DUMMYFVAR:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtest1Edummyf", members = {<#[[DUMMYDATA]], 0>}>
+// ALL: #[[DUMMYASVAR:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtest1Edummyas", members = {<#[[DUMMYDATA]], 0>}>
+// ALL: #[[DUMMYAVAR:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data/_QFtest1Edummya", members = {<#[[DUMMYDATA]], 0>}>
+// LOCAL: #[[LOCALDATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[DUMMYFTAG:.+]] = #llvm.tbaa_tag<base_type = #[[DUMMYFVAR]], access_type = #[[DUMMYFVAR]], offset = 0>
+// ALL: #[[DUMMYASTAG:.+]] = #llvm.tbaa_tag<base_type = #[[DUMMYASVAR]], access_type = #[[DUMMYASVAR]], offset = 0>
+// ALL: #[[DUMMYATAG:.+]] = #llvm.tbaa_tag<base_type = #[[DUMMYAVAR]], access_type = #[[DUMMYAVAR]], offset = 0>
+// ALL: #[[GLOBVAR:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMdataEglob", members = {<#[[GLOBALDATA]], 0>}>
+// ALL: #[[GLOBTVAR:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMdataEglobt", members = {<#[[GLOBALDATA]], 0>}>
+// ALL: #[[GLOBAVAR:.+]] = #llvm.tbaa_type_desc<id = "direct data/_QMdataEgloba", members = {<#[[DIRECTDATA]], 0>}>
+// ALL: #[[GLOBATVAR:.+]] = #llvm.tbaa_type_desc<id = "direct data/_QMdataEglobat", members = {<#[[DIRECTDATA]], 0>}>
+// LOCAL: #[[LOCALVAR:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtest1Elocal", members = {<#[[LOCALDATA]], 0>}>
+// LOCAL: #[[LOCALTVAR:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtest1Elocalt", members = {<#[[LOCALDATA]], 0>}>
+// LOCAL: #[[LOCALAVAR:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtest1Elocala", members = {<#[[LOCALDATA]], 0>}>
+// LOCAL: #[[LOCALATVAR:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtest1Elocalat", members = {<#[[LOCALDATA]], 0>}>
+// ALL: #[[GLOBTAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOBVAR]], access_type = #[[GLOBVAR]], offset = 0>
+// ALL: #[[GLOBTTAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOBTVAR]], access_type = #[[GLOBTVAR]], offset = 0>
+// ALL: #[[GLOBATAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOBAVAR]], access_type = #[[GLOBAVAR]], offset = 0>
+// ALL: #[[GLOBATTAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOBATVAR]], access_type = #[[GLOBATVAR]], offset = 0>
+// LOCAL: #[[LOCALTAG:.+]] = #llvm.tbaa_tag<base_type = #[[LOCALVAR]], access_type = #[[LOCALVAR]], offset = 0>
+// LOCAL: #[[LOCALTTAG:.+]] = #llvm.tbaa_tag<base_type = #[[LOCALTVAR]], access_type = #[[LOCALTVAR]], offset = 0>
+// LOCAL: #[[LOCALATAG:.+]] = #llvm.tbaa_tag<base_type = #[[LOCALAVAR]], access_type = #[[LOCALAVAR]], offset = 0>
+// LOCAL: #[[LOCALATTAG:.+]] = #llvm.tbaa_tag<base_type = #[[LOCALATVAR]], access_type = #[[LOCALATVAR]], offset = 0>
+
+module {
+ fir.global @_QMdataEglob : !fir.array<10xf32> {
+ %0 = fir.zero_bits !fir.array<10xf32>
+ fir.has_value %0 : !fir.array<10xf32>
+ }
+ fir.global @_QMdataEgloba : !fir.box<!fir.heap<!fir.array<?xf32>>> {
+ %c0 = arith.constant 0 : index
+ %0 = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+ %1 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %2 = fir.embox %0(%1) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+ fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xf32>>>
+ }
+ fir.global @_QMdataEglobat target : !fir.box<!fir.heap<!fir.array<?xf32>>> {
+ %c0 = arith.constant 0 : index
+ %0 = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+ %1 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %2 = fir.embox %0(%1) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+ fir.has_value %2 : !fir.box<!fir.heap<!fir.array<?xf32>>>
+ }
+ fir.global @_QMdataEglobp : !fir.box<!fir.ptr<!fir.array<?xf32>>> {
+ %c0 = arith.constant 0 : index
+ %0 = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
+ %1 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %2 = fir.embox %0(%1) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+ fir.has_value %2 : !fir.box<!fir.ptr<!fir.array<?xf32>>>
+ }
+ fir.global @_QMdataEglobt target : !fir.array<10xf32> {
+ %0 = fir.zero_bits !fir.array<10xf32>
+ fir.has_value %0 : !fir.array<10xf32>
+ }
+
+// ALL-LABEL: func.func @_QPtest1(
+ func.func @_QPtest1(%arg0: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "dummyf"}, %arg1: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "dummyft", fir.target}, %arg2: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "dummyas"}, %arg3: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "dummyast", fir.target}, %arg4: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "dummya"}, %arg5: !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {fir.bindc_name = "dummyat", fir.target}, %arg6: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> {fir.bindc_name = "dummyp"}) {
+ %c0_i64 = arith.constant 0 : i64
+ %c1 = arith.constant 1 : index
+ %cst = arith.constant 1.000000e+00 : f32
+ %c0 = arith.constant 0 : index
+ %c10 = arith.constant 10 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.declare %arg4 dummy_scope %0 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest1Edummya"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %2 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFtest1Edummyas"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %3 = fir.declare %arg3 dummy_scope %0 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest1Edummyast"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> !fir.box<!fir.array<?xf32>>
+ %4 = fir.declare %arg5 dummy_scope %0 {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QFtest1Edummyat"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>, !fir.dscope) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %5 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %6 = fir.declare %arg0(%5) dummy_scope %0 {uniq_name = "_QFtest1Edummyf"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<10xf32>>
+ %7 = fir.declare %arg1(%5) dummy_scope %0 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest1Edummyft"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, !fir.dscope) -> !fir.ref<!fir.array<10xf32>>
+ %8 = fir.declare %arg6 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest1Edummyp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.dscope) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %9 = fir.address_of(@_QMdataEglob) : !fir.ref<!fir.array<10xf32>>
+ %10 = fir.declare %9(%5) {uniq_name = "_QMdataEglob"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %11 = fir.address_of(@_QMdataEgloba) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %12 = fir.declare %11 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMdataEgloba"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %13 = fir.address_of(@_QMdataEglobat) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %14 = fir.declare %13 {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QMdataEglobat"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %15 = fir.address_of(@_QMdataEglobp) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %16 = fir.declare %15 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMdataEglobp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %17 = fir.address_of(@_QMdataEglobt) : !fir.ref<!fir.array<10xf32>>
+ %18 = fir.declare %17(%5) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMdataEglobt"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %19 = fir.alloca !fir.array<10xf32> {bindc_name = "local", uniq_name = "_QFtest1Elocal"}
+ %20 = fir.declare %19(%5) {uniq_name = "_QFtest1Elocal"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %21 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "locala", uniq_name = "_QFtest1Elocala"}
+ %22 = fir.zero_bits !fir.heap<!fir.array<?xf32>>
+ %23 = fir.shape %c0 : (index) -> !fir.shape<1>
+ %24 = fir.embox %22(%23) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xf32>>>
+// ALL-NOT: fir.store{{.*}}tbaa
+ fir.store %24 to %21 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %25 = fir.declare %21 {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest1Elocala"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %26 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "localat", fir.target, uniq_name = "_QFtest1Elocalat"}
+// ALL-NOT: fir.store{{.*}}tbaa
+ fir.store %24 to %26 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %27 = fir.declare %26 {fortran_attrs = #fir.var_attrs<allocatable, target>, uniq_name = "_QFtest1Elocalat"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %28 = fir.alloca !fir.box<!fir.ptr<!fir.array<?xf32>>> {bindc_name = "localp", uniq_name = "_QFtest1Elocalp"}
+ %29 = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
+ %30 = fir.embox %29(%23) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+// ALL-NOT: fir.store{{.*}}tbaa
+ fir.store %30 to %28 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %31 = fir.declare %28 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest1Elocalp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %32 = fir.alloca !fir.array<10xf32> {bindc_name = "localt", fir.target, uniq_name = "_QFtest1Elocalt"}
+ %33 = fir.declare %32(%5) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtest1Elocalt"} : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %34 = fir.array_coor %10(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// module data :: real :: glob(10)
+// ALL: fir.store{{.*}}{tbaa = [#[[GLOBTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %34 : !fir.ref<f32>
+ %35 = fir.array_coor %18(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// module data :: real, target :: globt(10)
+// ALL: fir.store{{.*}}{tbaa = [#[[GLOBTTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %35 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %36 = fir.load %12 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %37 = fir.box_addr %36 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %38:3 = fir.box_dims %36, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %39 = fir.shape_shift %38#0, %38#1 : (index, index) -> !fir.shapeshift<1>
+ %40 = fir.array_coor %37(%39) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// module data :: real, allocatable :: globa(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[GLOBATAG]]]} : !fir.ref<f32>
+ fir.store %cst to %40 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %41 = fir.load %14 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %42 = fir.box_addr %41 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %43:3 = fir.box_dims %41, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %44 = fir.shape_shift %43#0, %43#1 : (index, index) -> !fir.shapeshift<1>
+ %45 = fir.array_coor %42(%44) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// module data :: real, allocatable, target :: globat(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[GLOBATTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %45 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %46 = fir.load %16 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %47:3 = fir.box_dims %46, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %48 = fir.shift %47#0 : (index) -> !fir.shift<1>
+ %49 = fir.array_coor %46(%48) %c1 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
+// module data :: real, pointer :: globp(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %49 : !fir.ref<f32>
+ %50 = fir.array_coor %6(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// real :: dummyf(10)
+// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYFTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %50 : !fir.ref<f32>
+ %51 = fir.array_coor %7(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// real, target :: dummyft(10)
+// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %51 : !fir.ref<f32>
+ %52 = fir.array_coor %2 %c1 : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+// real :: dummyas(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYASTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %52 : !fir.ref<f32>
+ %53 = fir.array_coor %3 %c1 : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
+// real, target :: dummyast(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %53 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %54 = fir.load %1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %55 = fir.box_addr %54 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %56:3 = fir.box_dims %54, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %57 = fir.shape_shift %56#0, %56#1 : (index, index) -> !fir.shapeshift<1>
+ %58 = fir.array_coor %55(%57) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// real, allocatable :: dummya(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[DUMMYATAG]]]} : !fir.ref<f32>
+ fir.store %cst to %58 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %59 = fir.load %4 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %60 = fir.box_addr %59 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %61:3 = fir.box_dims %59, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %62 = fir.shape_shift %61#0, %61#1 : (index, index) -> !fir.shapeshift<1>
+ %63 = fir.array_coor %60(%62) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// real, allocatable, target :: dummyat(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %63 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %64 = fir.load %8 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %65:3 = fir.box_dims %64, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %66 = fir.shift %65#0 : (index) -> !fir.shift<1>
+ %67 = fir.array_coor %64(%66) %c1 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
+// real, pointer :: dummyp(:)
+// ALL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %67 : !fir.ref<f32>
+ %68 = fir.array_coor %20(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// real :: local(10)
+// DEFAULT-NOT: fir.store{{.*}}tbaa
+// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %68 : !fir.ref<f32>
+ %69 = fir.array_coor %33(%5) %c1 : (!fir.ref<!fir.array<10xf32>>, !fir.shape<1>, index) -> !fir.ref<f32>
+// real, target :: localt(10)
+// DEFAULT-NOT: fir.store{{.*}}tbaa
+// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALTTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %69 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %70 = fir.load %25 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %71 = fir.box_addr %70 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %72:3 = fir.box_dims %70, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %73 = fir.shape_shift %72#0, %72#1 : (index, index) -> !fir.shapeshift<1>
+ %74 = fir.array_coor %71(%73) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// real, allocatable :: locala(:)
+// DEFAULT-NOT: fir.store{{.*}}tbaa
+// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALATAG]]]} : !fir.ref<f32>
+ fir.store %cst to %74 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %75 = fir.load %27 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %76 = fir.box_addr %75 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %77:3 = fir.box_dims %75, %c0 : (!fir.box<!fir.heap<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %78 = fir.shape_shift %77#0, %77#1 : (index, index) -> !fir.shapeshift<1>
+ %79 = fir.array_coor %76(%78) %c1 : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>, index) -> !fir.ref<f32>
+// real, allocatable, target :: localat(:)
+// DEFAULT-NOT: fir.store{{.*}}tbaa
+// LOCAL: fir.store{{.*}}{tbaa = [#[[LOCALATTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %79 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %80 = fir.load %31 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
+ %81:3 = fir.box_dims %80, %c0 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, index) -> (index, index, index)
+ %82 = fir.shift %81#0 : (index) -> !fir.shift<1>
+ %83 = fir.array_coor %80(%82) %c1 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
+// real, pointer :: localp(:)
+// DEFAULT-NOT: fir.store{{.*}}tbaa
+// LOCAL: fir.store{{.*}}{tbaa = [#[[TARGETTAG]]]} : !fir.ref<f32>
+ fir.store %cst to %83 : !fir.ref<f32>
+// ALL-NOT: fir.load{{.*}}tbaa
+ %84 = fir.load %27 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %85 = fir.box_addr %84 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %86 = fir.convert %85 : (!fir.heap<!fir.array<?xf32>>) -> i64
+ %87 = arith.cmpi ne, %86, %c0_i64 : i64
+ fir.if %87 {
+// ALL-NOT: fir.load{{.*}}tbaa
+ %92 = fir.load %27 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %93 = fir.box_addr %92 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ fir.freemem %93 : !fir.heap<!fir.array<?xf32>>
+// ALL-NOT: fir.store{{.*}}tbaa
+ fir.store %24 to %27 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ }
+// ALL-NOT: fir.load{{.*}}tbaa
+ %88 = fir.load %25 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %89 = fir.box_addr %88 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ %90 = fir.convert %89 : (!fir.heap<!fir.array<?xf32>>) -> i64
+ %91 = arith.cmpi ne, %90, %c0_i64 : i64
+ fir.if %91 {
+// ALL-NOT: fir.load{{.*}}tbaa
+ %92 = fir.load %25 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ %93 = fir.box_addr %92 : (!fir.box<!fir.heap<!fir.array<?xf32>>>) -> !fir.heap<!fir.array<?xf32>>
+ fir.freemem %93 : !fir.heap<!fir.array<?xf32>>
+// ALL-NOT: fir.store{{.*}}tbaa
+ fir.store %24 to %25 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>>
+ }
+ return
+ }
+}
>From 0699f182228dd7ec08cdb4da5f73af0666c87b41 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Wed, 23 Apr 2025 12:53:07 -0700
Subject: [PATCH 2/2] Added common/equivalence test.
---
flang/test/Transforms/tbaa3.fir | 2 +-
flang/test/Transforms/tbaa4.fir | 177 ++++++++++++++++++++++++++++++++
2 files changed, 178 insertions(+), 1 deletion(-)
create mode 100644 flang/test/Transforms/tbaa4.fir
diff --git a/flang/test/Transforms/tbaa3.fir b/flang/test/Transforms/tbaa3.fir
index 4fb9a095279ea..28ff8f7c5fa83 100644
--- a/flang/test/Transforms/tbaa3.fir
+++ b/flang/test/Transforms/tbaa3.fir
@@ -63,7 +63,7 @@
// | |- "global data/_QMdataEglob"
// | |- "global data/_QMdataEglobt"
// |
-// |- "direct data" - "direct data/_QMdataEgloba"
+// |- "direct data"
// | |
// | |- "direct data/_QMdataEgloba"
// | |- "direct data/_QMdataEglobat"
diff --git a/flang/test/Transforms/tbaa4.fir b/flang/test/Transforms/tbaa4.fir
new file mode 100644
index 0000000000000..6fa8fff02b6a6
--- /dev/null
+++ b/flang/test/Transforms/tbaa4.fir
@@ -0,0 +1,177 @@
+// Test TBAA tags for common and equivalence.
+// RUN: fir-opt --fir-add-alias-tags --split-input-file %s | FileCheck --check-prefixes=ALL,DEFAULT %s
+// RUN: fir-opt --fir-add-alias-tags --local-alloc-tbaa --split-input-file %s | FileCheck --check-prefixes=ALL,LOCAL %s
+
+// ALL: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest_common">
+// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
+// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY]], 0>}>
+// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA]], 0>}>
+// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[BLK:.+]] = #llvm.tbaa_type_desc<id = "global data/blk_", members = {<#[[GLOBALDATA]], 0>}>
+// ALL: #[[TAG:.+]] = #llvm.tbaa_tag<base_type = #[[BLK]], access_type = #[[BLK]], offset = 0>
+
+module {
+// ALL-LABEL: fir.global common @blk_(dense<0> : vector<48xi8>) {alignment = 4 : i64} : !fir.array<48xi8>
+ fir.global common @blk_(dense<0> : vector<48xi8>) {alignment = 4 : i64} : !fir.array<48xi8>
+
+// ALL-LABEL: func.func @_QPtest_common() {
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<f32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<i32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<f32>
+ func.func @_QPtest_common() {
+ %c1 = arith.constant 1 : index
+ %c1_i32 = arith.constant 1 : i32
+ %cst = arith.constant 1.000000e+00 : f32
+ %c10 = arith.constant 10 : index
+ %c8 = arith.constant 8 : index
+ %c4 = arith.constant 4 : index
+ %c0 = arith.constant 0 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.address_of(@blk_) : !fir.ref<!fir.array<48xi8>>
+ %2 = fir.convert %1 : (!fir.ref<!fir.array<48xi8>>) -> !fir.ref<!fir.array<?xi8>>
+ %3 = fir.coordinate_of %2, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
+ %4 = fir.convert %3 : (!fir.ref<i8>) -> !fir.ref<f32>
+ %5 = fir.declare %4 {uniq_name = "_QFtest_commonEa"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %6 = fir.coordinate_of %2, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
+ %7 = fir.convert %6 : (!fir.ref<i8>) -> !fir.ref<f32>
+ %8 = fir.declare %7 {uniq_name = "_QFtest_commonEb"} : (!fir.ref<f32>) -> !fir.ref<f32>
+ %9 = fir.coordinate_of %2, %c8 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
+ %10 = fir.convert %9 : (!fir.ref<i8>) -> !fir.ref<!fir.array<10xi32>>
+ %11 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %12 = fir.declare %10(%11) {uniq_name = "_QFtest_commonEc"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<10xi32>>
+ fir.store %cst to %5 : !fir.ref<f32>
+ %13 = fir.array_coor %12(%11) %c1 : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c1_i32 to %13 : !fir.ref<i32>
+ fir.store %cst to %8 : !fir.ref<f32>
+ return
+ }
+}
+
+// -----
+
+// LOCAL: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest_local_equiv">
+// LOCAL: #[[ANY:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
+// LOCAL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY]], 0>}>
+// LOCAL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA]], 0>}>
+// LOCAL: #[[ALLOCATEDDATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[TARGETDATA]], 0>}>
+// LOCAL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtest_local_equivEa", members = {<#[[ALLOCATEDDATA]], 0>}>
+// LOCAL: #[[$ATTR_13:.+]] = #llvm.tbaa_tag<base_type = #[[EQUIV]], access_type = #[[EQUIV]], offset = 0>
+
+// ALL-LABEL: func.func @_QPtest_local_equiv() {
+// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<i32>
+// LOCAL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+// DEFAULT-NOT: fir.store{{.}}tbaa
+func.func @_QPtest_local_equiv() {
+ %c1 = arith.constant 1 : index
+ %c1_i32 = arith.constant 1 : i32
+ %cst = arith.constant 1.000000e+00 : f32
+ %c10 = arith.constant 10 : index
+ %c0 = arith.constant 0 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca !fir.array<40xi8> {uniq_name = "_QFtest_local_equivEa"}
+ %2 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ptr<f32>
+ %4 = fir.declare %3 {uniq_name = "_QFtest_local_equivEa"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %5 = fir.declare %3 {uniq_name = "_QFtest_local_equivEb"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %6 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %7 = fir.convert %6 : (!fir.ref<i8>) -> !fir.ptr<!fir.array<10xi32>>
+ %8 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %9 = fir.declare %7(%8) {uniq_name = "_QFtest_local_equivEc"} : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.ptr<!fir.array<10xi32>>
+ fir.store %cst to %4 : !fir.ptr<f32>
+ %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c1_i32 to %10 : !fir.ref<i32>
+ fir.store %cst to %5 : !fir.ptr<f32>
+ return
+}
+
+// -----
+
+// ALL: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest_save_equiv">
+// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
+// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY]], 0>}>
+// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA]], 0>}>
+// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc<id = "global data/_QFtest_save_equivEa", members = {<#[[GLOBALDATA]], 0>}>
+// ALL: #[[TAG:.+]] = #llvm.tbaa_tag<base_type = #[[EQUIV]], access_type = #[[EQUIV]], offset = 0>
+module {
+// ALL-LABEL: fir.global internal @_QFtest_save_equivEa : !fir.array<40xi8> {
+ fir.global internal @_QFtest_save_equivEa : !fir.array<40xi8> {
+ %0 = fir.zero_bits !fir.array<40xi8>
+ fir.has_value %0 : !fir.array<40xi8>
+ }
+
+// ALL-LABEL: func.func @_QPtest_save_equiv() {
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<i32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+ func.func @_QPtest_save_equiv() {
+ %c1 = arith.constant 1 : index
+ %c1_i32 = arith.constant 1 : i32
+ %cst = arith.constant 1.000000e+00 : f32
+ %c10 = arith.constant 10 : index
+ %c0 = arith.constant 0 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.address_of(@_QFtest_save_equivEa) : !fir.ref<!fir.array<40xi8>>
+ %2 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ptr<f32>
+ %4 = fir.declare %3 {uniq_name = "_QFtest_save_equivEa"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %5 = fir.declare %3 {uniq_name = "_QFtest_save_equivEb"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %6 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %7 = fir.convert %6 : (!fir.ref<i8>) -> !fir.ptr<!fir.array<10xi32>>
+ %8 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %9 = fir.declare %7(%8) {uniq_name = "_QFtest_save_equivEc"} : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.ptr<!fir.array<10xi32>>
+ fir.store %cst to %4 : !fir.ptr<f32>
+ %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c1_i32 to %10 : !fir.ref<i32>
+ fir.store %cst to %5 : !fir.ptr<f32>
+ return
+ }
+}
+
+// -----
+
+// ALL: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest_global_equiv">
+// ALL: #[[ANY:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
+// ALL: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY]], 0>}>
+// ALL: #[[TARGETDATA:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA]], 0>}>
+// ALL: #[[GLOBALDATA:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA]], 0>}>
+// ALL: #[[EQUIV:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMdataEa", members = {<#[[GLOBALDATA]], 0>}>
+// ALL: #[[TAG:.+]] = #llvm.tbaa_tag<base_type = #[[EQUIV]], access_type = #[[EQUIV]], offset = 0>
+
+module {
+// ALL-LABEL: fir.global @_QMdataEa : !fir.array<40xi8> {
+ fir.global @_QMdataEa : !fir.array<40xi8> {
+ %0 = fir.zero_bits !fir.array<40xi8>
+ fir.has_value %0 : !fir.array<40xi8>
+ }
+// ALL-LABEL: func.func @_QPtest_global_equiv() {
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ref<i32>
+// ALL: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
+ func.func @_QPtest_global_equiv() {
+ %c1 = arith.constant 1 : index
+ %c1_i32 = arith.constant 1 : i32
+ %cst = arith.constant 1.000000e+00 : f32
+ %c10 = arith.constant 10 : index
+ %c0 = arith.constant 0 : index
+ %c8 = arith.constant 8 : index
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.address_of(@_QMdataEa) : !fir.ref<!fir.array<40xi8>>
+ %2 = fir.coordinate_of %1, %c8 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ptr<f32>
+ %4 = fir.declare %3 {uniq_name = "_QMdataEa"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %5 = fir.declare %3 {uniq_name = "_QMdataEb"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
+ %6 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<40xi8>>, index) -> !fir.ref<i8>
+ %7 = fir.convert %6 : (!fir.ref<i8>) -> !fir.ptr<!fir.array<10xi32>>
+ %8 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %9 = fir.declare %7(%8) {uniq_name = "_QMdataEc"} : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>) -> !fir.ptr<!fir.array<10xi32>>
+ fir.store %cst to %4 : !fir.ptr<f32>
+ %10 = fir.array_coor %9(%8) %c1 : (!fir.ptr<!fir.array<10xi32>>, !fir.shape<1>, index) -> !fir.ref<i32>
+ fir.store %c1_i32 to %10 : !fir.ref<i32>
+ fir.store %cst to %5 : !fir.ptr<f32>
+ return
+ }
+}
More information about the flang-commits
mailing list