-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[flang][TBAA] refine TARGET/POINTER encoding #170908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thanks for handling the COMMON case, Tom! I think it is okay to have tags for different COMMON variables in different subtrees. I am not sure if anything within the same function can alias with the whole common block. |
edaf9d8 to
5270d73
Compare
Re-land llvm#169544 Previously we were less specific for POINTER/TARGET: encoding that they could alias with (almost) anything. In the new system, the "target data" tree is now a sibling of the other trees (e.g. "global data"). POITNTER variables go at the root of the "target data" tree, whereas TARGET variables get their own nodes under that tree. For example, ``` integer, pointer :: ip real, pointer :: rp integer, target :: it integer, target :: it2(:) real, target :: rt integer :: i real :: r ``` - `ip` and `rp` may alias with any variable except `i` and `r`. - `it`, `it2`, and `rt` may alias only with `ip` or `rp`. - `i` and `r` cannot alias with any other variable. Fortran 2023 15.5.2.14 gives restrictions on entities associated with dummy arguments. These do not allow non-target globals to be modified through dummy arguments and therefore I don't think we need to make all globals alias with dummy arguments. I haven't implemented it in this patch, but I wonder whether it is ever possible for `ip` to alias with `rt` or even `it2`. While I was updating the tests I fixed up some tests that still assumed that local alloc tbaa wasn't the default. I found no functional regressions in the gfortran test suite, fujitsu test suite, spec2017, or a selection of HPC apps we test internally.
Fixes func_result_6.f90 from gfortran testsuite. I also added some LLVM_DEBUG output showing the source reported by the FIR alias analysis.
TARGET variables inside of a common block will be added under the TARGET tree instead of the global tree so that they alias with all pointers. This means that the common block root cannot be used to alias with the whole common block, but I don't think that is used anywhere.
See discussion on llvm#170900
5270d73 to
c996e31
Compare
|
Ready for review. |
|
@llvm/pr-subscribers-flang-driver @llvm/pr-subscribers-flang-fir-hlfir Author: Tom Eccles (tblah) ChangesDepends upon #170900 Re-land #169544 Previously we were less specific for POINTER/TARGET: encoding that they In the new system, the "target data" tree is now a sibling of the other
Fortran 2023 15.5.2.14 gives restrictions on entities associated with I haven't implemented it in this patch, but I wonder whether it is ever While I was updating the tests I fixed up some tests that still assumed Cray pointers/pointees are (optionally) modelled as aliasing with all non-descriptor data. This is not enabled by default. I found no functional regressions in the gfortran test suite. Patch is 74.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170908.diff 14 Files Affected:
diff --git a/flang/include/flang/Optimizer/Analysis/TBAAForest.h b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
index b4932594114a1..0b70778eba3af 100644
--- a/flang/include/flang/Optimizer/Analysis/TBAAForest.h
+++ b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
@@ -99,11 +99,25 @@ struct TBAATree {
// |- "any data access"
// |
// |- "dummy arg data"
- // |- "target data"
- // |
- // |- "allocated data"
- // |- "direct data"
- // |- "global data"
+ // |
+ // |- <dummy arg name 1>
+ // |- <dummy arg name 2>
+ // |- "target data" <-- Any POINTER variable or TARGET dummy arg
+ // |
+ // |- <target name 1> <--- any TARGET variable which isn't a dummy arg
+ // |- <target name 2>
+ // |- "allocated data"
+ // |
+ // |- <allocated name 1>
+ // |- <allocated name 2>
+ // |- "direct data"
+ // |
+ // |- <direct name 1>
+ // |- <direct name 2>
+ // |- "global data"
+ // |
+ // |- <global name 1>
+ // |- <global name 2>
static TBAATree buildTree(mlir::StringAttr functionName);
private:
diff --git a/flang/lib/Optimizer/Analysis/TBAAForest.cpp b/flang/lib/Optimizer/Analysis/TBAAForest.cpp
index 44a0348da3a6f..7154785c62c75 100644
--- a/flang/lib/Optimizer/Analysis/TBAAForest.cpp
+++ b/flang/lib/Optimizer/Analysis/TBAAForest.cpp
@@ -66,12 +66,9 @@ fir::TBAATree::TBAATree(mlir::LLVM::TBAATypeDescriptorAttr anyAccess,
mlir::LLVM::TBAATypeDescriptorAttr dataRoot,
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc)
: targetDataTree(dataRoot.getContext(), "target data", dataRoot),
- globalDataTree(dataRoot.getContext(), "global data",
- targetDataTree.getRoot()),
- allocatedDataTree(dataRoot.getContext(), "allocated data",
- targetDataTree.getRoot()),
+ globalDataTree(dataRoot.getContext(), "global data", dataRoot),
+ allocatedDataTree(dataRoot.getContext(), "allocated data", dataRoot),
dummyArgDataTree(dataRoot.getContext(), "dummy arg data", dataRoot),
- directDataTree(dataRoot.getContext(), "direct data",
- targetDataTree.getRoot()),
+ directDataTree(dataRoot.getContext(), "direct data", dataRoot),
anyAccessDesc(anyAccess), boxMemberTypeDesc(boxMemberTypeDesc),
anyDataTypeDesc(dataRoot) {}
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 0221c7a8184d7..558ffa1a80bcf 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -60,6 +60,9 @@ static llvm::cl::opt<unsigned> localAllocsThreshold(
llvm::cl::desc("If present, stops generating TBAA tags for accesses of "
"local allocations after N accesses in a module"));
+// Defined in AliasAnalysis.cpp
+extern llvm::cl::opt<bool> supportCrayPointers;
+
namespace {
// Return the size and alignment (in bytes) for the given type.
@@ -668,6 +671,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs() << "Analysing " << op << "\n");
const fir::AliasAnalysis::Source &source = state.getSource(memref);
+ LLVM_DEBUG(llvm::dbgs() << "Got source " << source << "\n");
// Process the scopes, if not processed yet.
state.processFunctionScopes(func);
@@ -686,14 +690,22 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
}
mlir::LLVM::TBAATagAttr tag;
- // TBAA for dummy arguments
- if (enableDummyArgs &&
- source.kind == fir::AliasAnalysis::SourceKind::Argument) {
+ // Cray pointer/pointee is a special case. These might alias with any data.
+ if (supportCrayPointers && source.isCrayPointerOrPointee()) {
+ LLVM_DEBUG(llvm::dbgs().indent(2)
+ << "Found reference to Cray pointer/pointee at " << *op << "\n");
+ mlir::LLVM::TBAATypeDescriptorAttr anyDataDesc =
+ state.getFuncTreeWithScope(func, scopeOp).anyDataTypeDesc;
+ tag = mlir::LLVM::TBAATagAttr::get(anyDataDesc, anyDataDesc, /*offset=*/0);
+ // TBAA for dummy arguments
+ } else if (enableDummyArgs &&
+ source.kind == fir::AliasAnalysis::SourceKind::Argument) {
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 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.
+ // POINTERS can alias with any POINTER or TARGET. Assume that TARGET dummy
+ // arguments might alias with each other (because of the "TARGET" hole for
+ // dummy arguments). See flang/docs/Aliasing.md.
if (source.isTargetOrPointer()) {
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
} else if (!name.empty()) {
@@ -715,13 +727,10 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to global " << globalName.str() << " at "
<< *op << "\n");
- if (source.isPointer()) {
- tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
- } else {
- // In general, place the tags under the "global data" root.
- fir::TBAATree::SubtreeState *subTree =
- &state.getMutableFuncTreeWithScope(func, scopeOp).globalDataTree;
+ // Add a named tag inside the given subtree, disambiguating members of a
+ // common block
+ auto addTagUsingStorageDesc = [&](fir::TBAATree::SubtreeState *subTree) {
mlir::Operation *instantiationPoint = source.origin.instantiationPoint;
auto storageIface =
mlir::dyn_cast_or_null<fir::FortranVariableStorageOpInterface>(
@@ -766,6 +775,19 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
LLVM_DEBUG(llvm::dbgs()
<< "Tagged under '" << globalName << "' root\n");
}
+ };
+
+ if (source.isPointer()) {
+ // Pointers can alias with any pointer or target.
+ tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ } else if (source.isTarget()) {
+ // Targets could alias with any pointer but not with each other.
+ addTagUsingStorageDesc(
+ &state.getMutableFuncTreeWithScope(func, scopeOp).targetDataTree);
+ } else {
+ // In general, place the tags under the "global data" root.
+ addTagUsingStorageDesc(
+ &state.getMutableFuncTreeWithScope(func, scopeOp).globalDataTree);
}
// TBAA for global variables with descriptors
@@ -776,9 +798,17 @@ 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");
+ // Pointer can alias with any pointer or target so that gets the root.
if (source.isPointer())
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ // Targets could alias with any pointer but not with each other so they
+ // get their own node inside of the target data tree.
+ else if (source.isTarget())
+ tag = state.getFuncTreeWithScope(func, scopeOp)
+ .targetDataTree.getTag(name);
else
+ // Boxes that are not pointers or targets cannot alias with those that
+ // are. Put them under global data.
tag = state.getFuncTreeWithScope(func, scopeOp)
.directDataTree.getTag(name);
} else {
@@ -815,8 +845,13 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
<< "\n");
} else if (source.isPointer() && state.attachLocalAllocTag()) {
LLVM_DEBUG(llvm::dbgs().indent(2)
- << "Found reference to allocation at " << *op << "\n");
+ << "Found reference to POINTER allocation at " << *op << "\n");
tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+ } else if (source.isTarget() && state.attachLocalAllocTag()) {
+ LLVM_DEBUG(llvm::dbgs().indent(2)
+ << "Found reference to TARGET allocation at " << *op << "\n");
+ tag = state.getFuncTreeWithScope(func, scopeOp)
+ .targetDataTree.getTag(*name);
} else if (name && state.attachLocalAllocTag()) {
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation "
<< name << " at " << *op << "\n");
diff --git a/flang/test/Driver/tco-test-gen.fir b/flang/test/Driver/tco-test-gen.fir
index b39295d72918f..438804ce42b76 100644
--- a/flang/test/Driver/tco-test-gen.fir
+++ b/flang/test/Driver/tco-test-gen.fir
@@ -77,13 +77,13 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re
// CHECK: llvm.cond_br %[[VAL_17]], ^bb2, ^bb3
// CHECK: ^bb2:
-// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
+// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr
// AA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "dummy arg data/_QFtestEnum", members = {<#llvm.tbaa_type_desc<id = "dummy arg data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_18:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
-// AA: %[[VAL_19:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
+// AA: %[[VAL_19:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_19:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32
// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_18]], %[[VAL_19]] : i32
@@ -92,7 +92,7 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re
// CHECK: %[[VAL_21:.*]] = llvm.trunc %[[VAL_10]] : i64 to i32
-// AA: %[[VAL_22:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
+// AA: %[[VAL_22:.*]] = llvm.load %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : !llvm.ptr -> i32
// NOAA: %[[VAL_22:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32
// CHECK: %[[VAL_23:.*]] = llvm.add %[[VAL_22]], %[[VAL_21]] overflow<nsw> : i32
@@ -100,7 +100,7 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re
// CHECK: llvm.br ^bb1(%[[VAL_23]], %[[VAL_24]] : i32, i64)
// CHECK: ^bb3:
-// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "target data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
+// AA: llvm.store %[[VAL_15]], %[[VAL_1]] {tbaa = [#llvm.tbaa_tag<base_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, access_type = <id = "allocated data/_QFtestEi", members = {<#llvm.tbaa_type_desc<id = "allocated data", members = {<#llvm.tbaa_type_desc<id = "any data access", members = {<#llvm.tbaa_type_desc<id = "any access", members = {<#llvm.tbaa_root<id = "Flang function root _QPtest">, 0>}>, 0>}>, 0>}>, 0>}>, offset = 0>]} : i32, !llvm.ptr
// NOAA: llvm.store %[[VAL_15]], %{{.*}} : i32, !llvm.ptr
// CHECK: llvm.return
diff --git a/flang/test/Fir/tbaa-codegen2.fir b/flang/test/Fir/tbaa-codegen2.fir
index 4907aa03ec5a5..071d3ec89394c 100644
--- a/flang/test/Fir/tbaa-codegen2.fir
+++ b/flang/test/Fir/tbaa-codegen2.fir
@@ -114,4 +114,3 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
// CHECK: ![[TMP_DATA_ACCESS_TAG]] = !{![[TMP_DATA_ACCESS_TYPE:.*]], ![[TMP_DATA_ACCESS_TYPE]], i64 0}
// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data/", ![[TMP_ACCESS_TYPE:.*]], i64 0}
// CHECK: ![[TMP_ACCESS_TYPE]] = !{!"allocated data", ![[TARGET_ACCESS_TAG:.*]], i64 0}
-// CHECK: ![[TARGET_ACCESS_TAG]] = !{!"target data", ![[DATA_ACCESS_TYPE]], i64 0}
diff --git a/flang/test/Transforms/tbaa-cray-pointer.fir b/flang/test/Transforms/tbaa-cray-pointer.fir
new file mode 100644
index 0000000000000..54406271aaa58
--- /dev/null
+++ b/flang/test/Transforms/tbaa-cray-pointer.fir
@@ -0,0 +1,43 @@
+// RUN: fir-opt -funsafe-cray-pointers --fir-add-alias-tags %s | FileCheck %s
+
+// Fortran source:
+// subroutine test()
+// real :: a, b
+// pointer(p, a)
+// p = loc(b)
+// b = 2
+// end subroutine
+
+// CHECK: #[[TBAA_ROOT:.*]] = #llvm.tbaa_root<id = "Flang function root _QPtest">
+// CHECK-NEXT: #[[ANY_ACCESS:.*]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[TBAA_ROOT]], 0>}>
+// CHECK-NEXT: #[[ANY_DATA:.*]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANY_ACCESS]], 0>}>
+// CHECK-NEXT: #[[ANY_DATA_TAG:.*]] = #llvm.tbaa_tag<base_type = #[[ANY_DATA]], access_type = #[[ANY_DATA]], offset = 0>
+// CHECK-NEXT: #[[ALLOCATED_DATA:.*]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[ANY_DATA]], 0>}>
+// CHECK-NEXT: #[[B:.*]] = #llvm.tbaa_type_desc<id = "allocated data/_QFtestEb", members = {<#[[ALLOCATED_DATA]], 0>}>
+// CHECK-NEXT: #[[B_TAG:.*]] = #llvm.tbaa_tag<base_type = #[[B]], access_type = #[[B]], offset = 0>
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vector<4xi64>, !llvm.ptr<271> = dense<32> : vector<4xi64>, !llvm.ptr<272> = dense<64> : vector<4xi64>, i8 = dense<[8, 32]> : vector<2xi64>, i16 = dense<[16, 32]> : vector<2xi64>, i64 = dense<64> : vector<2xi64>, i128 = dense<128> : vector<2xi64>, !llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little", "dlti.mangling_mode" = "e", "dlti.legal_int_widths" = array<i32: 32, 64>, "dlti.stack_alignment" = 128 : i64, "dlti.function_pointer_alignment" = #dlti.function_pointer_alignment<32, function_dependent = true>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"} {
+// CHECK-LABEL: func.func @_QPtest()
+ func.func @_QPtest() {
+ %cst = arith.constant 2.000000e+00 : f32
+ %0 = fir.alloca !fir.box<!fir.ptr<f32>>
+ %1 = fir.dummy_scope : !fir.dscope
+ %2 = fir.alloca i64 {bindc_name = "p", uniq_name = "_QFtestEp"}
+ %3 = fir.declare %2 {fortran_attrs = #fir.var_attrs<cray_pointer>, uniq_name = "_QFtestEp"} : (!fir.ref<i64>) -> !fir.ref<i64>
+ %4 = fir.alloca f32 {bindc_name = "b", uniq_name = "_QFtestEb"}
+ %5 = fir.declare %4...
[truncated]
|
vzakhari
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, Tom!
PR #170908 introduced an unconditional dereference of the local target variable name, but in rare cases (I am not sure this can be reproduced without `-mllvm -inline-all` currently), such variable may not have a uniq name on the alloca. For instance, this can happen after a call to a function with TARGET character result is inlined. The alloca is a temp on the caller side, that gets the TARGET attribute in the inlined scope via the result name.
Depends upon #170900
Re-land #169544
Previously we were less specific for POINTER/TARGET: encoding that they
could alias with (almost) anything.
In the new system, the "target data" tree is now a sibling of the other
trees (e.g. "global data"). POITNTER variables go at the root of the
"target data" tree, whereas TARGET variables get their own nodes under
that tree. For example,
ipandrpmay alias with any variable exceptiandr.it,it2, andrtmay alias only withiporrp.iandrcannot alias with any other variable.Fortran 2023 15.5.2.14 gives restrictions on entities associated with
dummy arguments. These do not allow non-target globals to be modified
through dummy arguments and therefore I don't think we need to make all
globals alias with dummy arguments.
I haven't implemented it in this patch, but I wonder whether it is ever
possible for
ipto alias withrt.While I was updating the tests I fixed up some tests that still assumed
that local alloc tbaa wasn't the default.
Cray pointers/pointees are (optionally) modelled as aliasing with all non-descriptor data. This is not enabled by default.
I found no functional regressions in the gfortran test suite.