This change basically treats the descriptors' and data loads
as non-aliasing (with one exception) same way as we do it
for the purpose of the TBAA tags generation for LLVM
to do better optimizations. This change enables more LICM in Flang MLIR.
We should ignore MemAlloc/Free effects as they are not
modifying/reading ones. This is what LocalAliasAnalysis
does. This patch also removes the operation-wide MemFree
effect from `fir.freemem`.
Support `cuf.device_address` same way as `fir.address_of`.
This implementation implies that the host address and the device
address `MustAlias` (as shown in the new test). This should be
conservatively correct as long as `MustAlias` does not allow
to assume that the actual addresses are the same (that is what
LLVM documentation implies, I believe).
It is probably worth adding an operation interface to handle
`fir::AddrOfOp` and `cuf::DeviceAddressOp` in FIR AliasAnalysis,
but for the initial implementation I hardcoded the checks.
I also removed the call to `fir::valueHasFirAttribute` that performs
on demand SymbolTable lookups, which may be costly, and added
SymbolTable caching in FIR AliasAnalysis object. Anyway,
`fir::valueHasFirAttribute` does not work for `cuf::DeviceAddressOp`.
Reserve "-funsafe-cray-pointers" (with "f") for the driver. In the
fir-alias-analysis use "-unsafe-cray-pointers" (without "f").
This prevents conflicts with how certain kinds of tools use the "unsafe
Cray pointers" options.
The new pass allows hoisting some `fir.load` operations early
in MLIR. For example, many descriptor load might be hoisted
out of the loops, though it does not make much difference
in performance, because LLVM is able to optimize such loads
(which are lowered as `llvm.memcpy` into temporary descriptors),
given that proper TBAA information is generated by Flang.
Further hoisting improvements are possible in [HL]FIR LICM,
e.g. getting proper mod-ref results for Fortran runtime calls
may allow hoisting loads from global variables, which LLVM
cannot do due to lack of alias information.
This patch also contains improvements for FIR mod-ref analysis:
We may recurse into `HasRecursiveMemoryEffects` operations and
use `getModRef` recursively to get more precise results for
regions with `fir.call` operations.
This patch also modifies `AliasAnalysis` to set the instantiation
point for cases where the tracked data is accessed through a load
from `!fir.ref<!fir.box<>>`: without this change the mod-ref
analysis was not able to recognize user pointer/allocatable variables.
I think this change should be equivalent to #170908 at MLIR level,
i.e. two distinct global variables cannot alias each other
even if they both have TARGET attribute.
The LOC intrinsic allows a cray pointer to alias with ordinary variables
with no other attribute. See the new test for an example.
This is not enabled by default. The functionality can be used with
`-mmlir -funsafe-cray-pointers`.
First part of the un-revert of #169544. That will handle TBAA.
This patch adds initial version of `FortranObjectViewOpInterface`
that helps walking def-use chains containing "pass-through"
operations (like `fir.convert`, etc.). The new interface is used
in FIR AliasAnalysis to demonstrate potential usage (I know we have
such walks elsewhere in Flang, but I am only changing FIR AliasAnalysis
in this patch).
This is an NFC change. I noticed that if I remove followBoxData
code there are no failing LIT tests, but I decided to keep it
in order to keep the change looking more like NFC.
This change is a follow-up on the discussion in #164020:
it is unclear if the `FortranObjectViewOpInterface` methods and their
usage, as in this patch, apply to the ViewLike operations that
use the core MLIR `ViewLikeOpInterface`. So this patch is the path
towards simplifying Flang code while also enabling a future discussion
about having such an interface in core MLIR.
Flang alias analysis used to find allocation site by pattern matching
allocation ops in mainly FIR dialect. This MR extends the
characterization to instead characterize based on whether the result of
an op has MemAlloc effect.
Early HLFIR optimizations may experience problems with values
produced by hlfir.associate. In most cases this is a unique
local memory allocation, but it can also reuse some other
hlfir.expr memory sometimes. It seems to be safe to assume
unique allocation for trivial types, since we always
allocate new memory for them.
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.
As mentioned at
<https://github.com/llvm/llvm-project/pull/126156#discussion_r1953523892>:
PR #126156 causes AliasAnalysis::getSource to sometimes return
SourceKind::Unknown when it used to return SourceKind::Indirect for a
LoadOp. This patch restores that part of the old behavior. It should not
affect user-visible behavior because AliasAnalysis::alias treats
SourceKind::Unknown and SourceKind::Indirect equivalently, but it does
improve debugging output.
Currently the alias analysis doesn't trace the source whenever there are
operations from fir::cg dialect. This PR added support for
fir::cg::XEmboxOp, fir::cg::XReboxOp, fir::cg::XDeclareOp for a specific
application i'm working on.
For example, determine that the address in `obj%p` below cannot alias
the address of `v`:
```
module m
type :: ty
real, pointer :: p
end type ty
end module m
subroutine test()
use m
real, target :: t
real :: v
type(ty) :: obj
obj%p => t
v = obj%p
end subroutine test
```
For example, determine that the address in p below cannot alias the
address of v:
```
subroutine test()
real, pointer :: p
real, target :: t
real :: v
p => t
v = p
end subroutine test
```
Typically, we do not track memory sources after a load because of the
dynamic nature of the load and the fact that the alias analysis is a
simple static analysis.
However, the code is written in a way that makes it seem like we are
continuing to track memory but in reality we are only doing so when we
know that the tracked memory is a leaf and therefore when there will
only be one more iteration through the switch statement. In other words,
we are iterating one more time, to gather data about a box, anticipating
that this will be the last time. This is a hack that helped avoid
cut-and-paste from other case statements but gives the wrong impression
about the intention of the code and makes it confusing.
To make it clear that there is no more tracking, we gather all the
necessary data from the memref of the load, in the case statement for
the load, and exit the loop. I am also limiting this data gathering for
the case when we load a box reference while we were actually following
data, as tests have shows, is the only case when we need it for. Other
cases will be handled conservatively, but this can change in the future,
on a case-by-case basis.
---------
Co-authored-by: Joel E. Denny <jdenny.ornl@gmail.com>
1. Our static functions are a bit spread out in this file. I am
gathering them in an anonymous namespace
2. Moving the code to get the `target` attribute on a `fir.global` into
its own utility.
Flang alias analysis crashes for omp private allocatable item. The issue
is described here : https://github.com/llvm/llvm-project/issues/116954 .
We know that private value can't alias with anything else unless it is POINTER
or TARGET. That's why we can simplify alias analysis logic.
Values can have no defining operation when the value is a blockarg. I
wrote this as a test for hlfir bufferization rather than alias analysis
because I couldn't find a way to add the test.ptr attribute to a block
argument.
This patch extends the optimize bufferization to deal with the new
hlfir.eval_in_mem and move the evaluation contained in its body to
operate directly over the LHS when it can prove there are no access to
the LHS inside the region (and that the LHS is contiguous).
This will allow the array function call optimization when lowering is
changed to produce an hlfir.eval_in_mem in the next patch.
fir.call side effects are hard to describe in a useful way using
`MemoryEffectOpInterface` because it is impossible to list which memory
location a user procedure read/write without doing a data flow analysis
of its body (even PURE procedures may read from any module variable,
Fortran SIMPLE procedure from F2023 will allow that, but they are far
from common at that point).
Fortran language specifications allow the compiler to deduce
that a procedure call cannot access a variable in many cases
This patch leverages this to extend `fir::AliasAnalysis::getModRef` to
deal with fir.call.
This will allow implementing "array = array_function()" optimization in
a future patch.
Enable alias analysis for omp private clause for code:
```
program main
integer :: arrayA(10,10)
integer :: tmp(2)
integer :: i,j
!$omp target teams distribute parallel do private(tmp)
do j = 1, 10
do i = 1,10
tmp = [i,j]
arrayA = tmp(1)
end do
end do
end program main
```
This PR is based on: https://github.com/llvm/llvm-project/pull/113566
and it contains fix for Fujitsu test suite. Previous PR introduced
regression in Fujitsu test suite. For some Fujitsu test cases
`omp.yield` operation points to block argument. Alias analysis for such
MLIR code will be added in separate PR.
Enable alias analysis for omp private clause for code:
```
program main
integer :: arrayA(10,10)
integer :: tmp(2)
integer :: i,j
!$omp target teams distribute parallel do private(tmp)
do j = 1, 10
do i = 1,10
tmp = [i,j]
arrayA = tmp(1)
end do
end do
end program main
```
This PR applies the changes discussed in [[RFC] Rationale for Flang
AliasAnalysis pointer component
logic](https://discourse.llvm.org/t/rfc-rationale-for-flang-aliasanalysis-pointer-component-logic/79252).
In summary, this PR replaces the existing pointer component logic in
Flang's AliasAnalysis implementation. That logic focuses on aliasing
between pointers and non-pointer, non-target composites that have
pointer components. However, it is more conservative than necessary, and
some existing tests expect its current results when less conservative
results seem reasonable.
This PR splits the logic into two cases:
1. Source values are the same: Return MayAlias when one value is the
address of a composite, and the other value is statically the address of
a pointer component of that composite.
2. Source values are different: Return MayAlias when one value is the
address of a composite (actual argument), and the other value is the
address of a pointer (dummy arg) that might dynamically be a component
of that composite.
In both cases, the actual implementation is still more conservative than
described above, but it can be improved further later. Details appear in
the comments.
Additionally, this PR revises the logic that reports MayAlias for a
pointer/target vs. another pointer/target. It constrains the existing
logic to handle only isData cases, and it adds less conservative
handling of !isData cases elsewhere. First, it extends case 2 listed
above to cover the case where the actual argument is the address of a
pointer rather than a composite. Second, it adds a third case: where
target attributes enable aliasing with a dummy argument.
This patch extends the alias analysis for temporary arrays in Flang.
With this extension, Flang can now determine that the temporary array
[a, b, c] does not alias with arrayD in Fortran code:
```
integer :: a, b, c
integer :: arrayD(3)
arrayD = [ a, b, c ]
```
At present, alias analysis does not work for operations inside OMP
target regions because the FIR declare operations within OMP target do
not offer sufficient information for alias analysis. Consequently, it is
necessary to examine the FIR code outside the OMP target region.
With MLIR inlining (e.g. `flang-new -mmlir -inline-all=true`)
the current TBAA tags attachment is suboptimal, because
we may lose information about the callee's dummy arguments
(by bypassing fir.declare in AliasAnalysis::getSource).
This is a conservative first step to improve the situation.
This patch makes AddAliasTagsPass to account for fir.dummy_scope
hierarchy after MLIR inlining and use it to place the TBAA tags
into TBAA trees corresponding to different function scopes.
The pass uses special mode of AliasAnalysis to find the instantiation
point of a Fortran variable (a [hl]fir.decalre) when searching
for the source of a memory reference. In this mode, AliasAnalysis
will always stop at fir.declare operations that have dummy_scope
operands - there should not be a reason to past throught it
for the purpose of TBAA tags attachment.
Fixes a bug uncovered by
[pr43337.f90](https://github.com/llvm/llvm-test-suite/blob/main/Fortran/gfortran/regression/gomp/pr43337.f90)
in the test suite.
In particular, this emits `argNo` debug info only if the parent op of a
block is a `func.func` op. This avoids DI conflicts when a function
contains a nested OpenMP region that itself has block arguments with DI
attached to them; for example, `omp.parallel` with delayed privatization
enabled.
This PR is an implementation for changes proposed in
https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759
Test updates were made when the query was on the wrong reference. So, it
is my hope that this will clear ambiguity on the nature of the queries
from here on.
There are also some TODOs that were addressed.
It also partly implements what
https://github.com/llvm/llvm-project/pull/87723 is attempting to
accomplish. At least, on a point-to-point query between references, the
distinction is made. To apply it to TBAA, would be another PR.
Note that, the changes were minimal in the TBAA code to retain the
current results.
Arguments to openmp regions should not be tagged as dummy arguments.
This is particularly unsafe because these openmp blocks will eventually
be inlined into the calling function, where they will trivially alias
with other values inside of the calling function.
This is probably a theoretical issue because the calls to openmp runtime
function calls would act as barriers, preventing optimizations that are
too aggressive. But a lot more thought would need to go into a bet like
that.
This came out of discussion on
https://github.com/llvm/llvm-project/pull/92036
…ted. (#89998)" (#90250)
This partially reverts commit 7aedd7dc754c74a49fe84ed2640e269c25414087.
This change removes calls to the deprecated member functions. It does
not mark the functions deprecated yet and does not disable the
deprecation warning in TypeSwitch. This seems to cause problems with
MSVC.
These hardcoded attribute name are a leftover from the upstreaming
period when there was no way to get the attribute name without an
instance of the operation. It is since possible to do without them and
they should be removed to avoid duplication.
This PR cleanup the fir.global op of these hardcoded attribute name and
use their generated getters. Some other PRs will follow to cleanup other
operations.
After PR#68727 the source for both the fir.box_addr and a box became the
same. Thus the detection that only one of the sources was direct and the
special logic around it was being skipped. As a result, the test
included would show a "MayAlias" result instead of a "NoAlias" result.
These turn out to be useful for spec2017/fotonik3d and safe so long as
they are not used along side TBAA tags for local allocations. LLVM may
be able to figure out local allocations by itself anyway.
PR #68727
The changes are needed to get leslie3d same performance with HLFIR
as with FIR lowering. The two module allocatable variables cannot
alias, so the optimized bufferization should be able to elide
the temporary and inline the assignment loop.
Add support for fir.box_addr, fir.array_corr, fir.coordinate, fir.embox,
fir.rebox and fir.load.
1) Through the use of boolean `followBoxAddr` determine whether the
analysis should apply to the address of the box or the address wrapped
by the box.
2) Some asserts have been removed to allow for more SourceKinds though
the flow, in a particular SourceKind::Direct
3) getSource was a public method but the returned type (SourceKind) was
not public making it impossible to be called publicly
4) About 12 tests have been added to check for real Fortran scenarios
5) More tests will be added with HLFIR
6) A few TODOs have been identified and will need to be addressed in
follow-up patches. I felt that more changes would increase the
complexity of the patch.
This patch adds `host_assoc` attribute for operations that implement
FortranVariableInterface (e.g. `hlfir.declare`). The attribute is used
by the alias analysis to make better conclusions about memory overlap.
For example, a dummy argument of an inner subroutine and a host's
variable used inside the inner subroutine cannot refer to the same
object (if the dummy argument does not satisify exceptions in F2018
15.5.2.13).
This closes a performance gap between HLFIR optimization pipeline
and FIR ArrayValueCopy for Polyhedron/nf.
Add a rough alias analysis rule for hlfir.designate which just follows
the memref argument. This could be extended in the future to take into
account the indices or derived type fields accessed to spot for provably
non-overlapping cases. In the meantime, we need a flag to ensure we
never say "MustAlias" when following a value through a hlfir.designate
because the designate analysis is only approximate.
Differential Revision: https://reviews.llvm.org/D157718