Tom Eccles 33fcfb37da
[flang][TBAA] refine TARGET/POINTER encoding (#170908)
Depends upon https://github.com/llvm/llvm-project/pull/170900

Re-land https://github.com/llvm/llvm-project/pull/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`.

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.
2025-12-11 10:03:43 +00:00

75 lines
3.1 KiB
C++

//===- TBAAForest.cpp - Per-functon TBAA Trees ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Analysis/TBAAForest.h"
#include <mlir/Dialect/LLVMIR/LLVMAttrs.h>
mlir::LLVM::TBAATagAttr
fir::TBAATree::SubtreeState::getTag(llvm::StringRef uniqueName) const {
std::string id = (parentId + '/' + uniqueName).str();
mlir::LLVM::TBAATypeDescriptorAttr type =
mlir::LLVM::TBAATypeDescriptorAttr::get(
context, id, mlir::LLVM::TBAAMemberAttr::get(parent, 0));
return mlir::LLVM::TBAATagAttr::get(type, type, 0);
}
fir::TBAATree::SubtreeState &
fir::TBAATree::SubtreeState::getOrCreateNamedSubtree(mlir::StringAttr name) {
auto it = namedSubtrees.find(name);
if (it != namedSubtrees.end())
return it->second;
return namedSubtrees
.insert(
{name, SubtreeState(context, parentId + '/' + name.str(), parent)})
.first->second;
}
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();
mlir::MLIRContext *ctx = func.getContext();
mlir::LLVM::TBAARootAttr funcRoot =
mlir::LLVM::TBAARootAttr::get(ctx, mlir::StringAttr::get(ctx, rootId));
static constexpr llvm::StringRef anyAccessTypeDescId = "any access";
mlir::LLVM::TBAATypeDescriptorAttr anyAccess =
mlir::LLVM::TBAATypeDescriptorAttr::get(
ctx, anyAccessTypeDescId,
mlir::LLVM::TBAAMemberAttr::get(funcRoot, 0));
static constexpr llvm::StringRef anyDataAccessTypeDescId = "any data access";
mlir::LLVM::TBAATypeDescriptorAttr dataRoot =
mlir::LLVM::TBAATypeDescriptorAttr::get(
ctx, anyDataAccessTypeDescId,
mlir::LLVM::TBAAMemberAttr::get(anyAccess, 0));
static constexpr llvm::StringRef boxMemberTypeDescId = "descriptor member";
mlir::LLVM::TBAATypeDescriptorAttr boxMemberTypeDesc =
mlir::LLVM::TBAATypeDescriptorAttr::get(
ctx, boxMemberTypeDescId,
mlir::LLVM::TBAAMemberAttr::get(anyAccess, 0));
return TBAATree{anyAccess, dataRoot, boxMemberTypeDesc};
}
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", dataRoot),
allocatedDataTree(dataRoot.getContext(), "allocated data", dataRoot),
dummyArgDataTree(dataRoot.getContext(), "dummy arg data", dataRoot),
directDataTree(dataRoot.getContext(), "direct data", dataRoot),
anyAccessDesc(anyAccess), boxMemberTypeDesc(boxMemberTypeDesc),
anyDataTypeDesc(dataRoot) {}