Skip to content

Commit 2253b06

Browse files
committed
[flang][NFC] Document Fortran aliasing rules
Summarize current understanding of Fortran's guarantees to a compiler (or in other words, restrictions on programs and programmers) about aliasing. Differential Revision: https://reviews.llvm.org/D135214
1 parent b7a0482 commit 2253b06

File tree

1 file changed

+355
-0
lines changed

1 file changed

+355
-0
lines changed

flang/docs/Aliasing.md

Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
<!--===- docs/Aliasing.md
2+
3+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
See https://llvm.org/LICENSE.txt for license information.
5+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
7+
-->
8+
9+
# Aliasing in Fortran
10+
11+
```eval_rst
12+
.. contents::
13+
:local:
14+
```
15+
16+
## Introduction
17+
18+
References to the ISO Fortran language standard here are given by subclause number
19+
or constraint number and pertain to Fortran 2018.
20+
21+
## Dummy Arguments
22+
23+
### Basic rule
24+
25+
Fortran famously passes actual arguments by reference, and forbids callers
26+
from associating multiple arguments on a call to conflicting storage when
27+
doing so would cause the called subprogram to write to a bit of that
28+
storage by means of one dummy argument and read or write that same bit
29+
by means of another.
30+
For example:
31+
```
32+
function f(a,b,j,k)
33+
real a(*), b(*)
34+
a(j) = 1.
35+
b(k) = 2.
36+
f = a(j) ! can optimize to: f = 1.
37+
end function
38+
```
39+
40+
This prohibition applies to programs (or programmers) and has been in place
41+
since Fortran acquired subroutines and functions in Fortran II.
42+
43+
A Fortran compiler is free to assume that a program conforms with this rule
44+
when optimizing; and while obvious violations should of course be diagnosed,
45+
the programmer bears the responsibility to understand and comply with this rule.
46+
47+
It should be noted that this restriction on dummy argument aliasing works
48+
"both ways", in general.
49+
Modifications to a dummy argument cannot affect other names by which that
50+
bit of storage may be known;
51+
conversely, modifications to anything other than a dummy argument cannot
52+
affect that dummy argument.
53+
54+
When a subprogram modifies storage by means of a particular dummy argument,
55+
Fortran's prohibition against dummy argument aliasing is not limited just to other
56+
dummy arguments, but to any other name by which that storage might be visible.
57+
For example:
58+
```
59+
module m
60+
real x
61+
contains
62+
function f(y)
63+
real y
64+
x = 1.
65+
y = 2.
66+
f = x ! can optimize to: f = 1.
67+
end function
68+
subroutine bad
69+
print *, f(x) ! nonconforming usage!
70+
end subroutine
71+
end module
72+
```
73+
74+
Similar examples can be written using variables in `COMMON` blocks, host-association
75+
in internal subprograms, and so forth.
76+
77+
Further, the general rule that a dummy argument by which some particular bit
78+
of storage has been modified must be the only means by which that storage is
79+
referenced during the lifetime of a subprogram extends to cover any associations
80+
with that dummy argument via pointer association, argument association in
81+
procedure references deeper on the call chain, and so on.
82+
83+
### Complications
84+
85+
Subclause 15.5.2.13 ("Restrictions on entities associated with dummy arguments"),
86+
which the reader is encouraged to try to understand despite its opacity,
87+
formalizes the rules for aliasing of dummy arguments.
88+
89+
In addition to the "basic rule" above, Fortran imposes these additional
90+
requirements on programs.
91+
92+
1. When a dummy argument is `ALLOCATABLE` or `POINTER`, it can be deallocated
93+
or reallocated only through the dummy argument during the life of the
94+
subprogram.
95+
1. When a dummy argument has a derived type with a component, possibly nested,
96+
that is `ALLOCATABLE` or `POINTER`, the same restriction applies.
97+
1. If a subprogram ever deallocates or reallocates a dummy argument or one of its
98+
components, the program cannot access that data by any other means, even
99+
before the change in allocation.
100+
101+
That subclause also *relaxes* the rules against dummy argument aliasing in
102+
some situations.
103+
104+
1. When a dummy argument is a `POINTER`, it is essentially treated like any
105+
other pointer for the purpose of alias analysis (see below), and its
106+
status as a dummy argument is reduced to being relevant only for
107+
deallocation and reallocation (see above).
108+
1. When a dummy argument is a `TARGET`, the actual argument is really
109+
a variable (not an expression or something that needs to be passed via
110+
a temporary), and that variable could be a valid data target in a pointer
111+
assignment statement, then the compiler has to worry about aliasing
112+
between that dummy argument and pointers if some other circumstances
113+
apply. (See the standard, this one is weird and complicated!)
114+
1. Aliasing doesn't extend its restrictions to what other images might do
115+
to a coarray dummy argument's associated local storage during the lifetime
116+
of a subprogram -- i.e., other images don't have to worry about avoiding
117+
accesses to the local image's storage when its coarray nature is explicit
118+
in the declaration of the dummy argument.
119+
(But when the local image's storage is associated with a non-coarray dummy
120+
argument, the rules still apply.
121+
In other words, the compiler doesn't have to worry about corrays unless
122+
it sees coarrays.)
123+
124+
### Implications for inlining
125+
126+
A naive implementation of inlining might rewrite a procedure reference
127+
something like this:
128+
```
129+
module m
130+
contains
131+
function addto(x, y)
132+
real, intent(in out) :: x
133+
real, intent(in) :: y
134+
x = x + y
135+
addto = y
136+
end function
137+
function f(a,j,k)
138+
real a(*)
139+
a(k) = 1.
140+
f = addto(a(j), a(k)) ! optimizable to 1.
141+
end function
142+
end module
143+
```
144+
145+
becoming, after inline expansion at the Fortran language level,
146+
147+
```
148+
function f(a,j,k)
149+
real a(*)
150+
a(k) = 1.
151+
a(j) = a(j) + a(k)
152+
f = a(k) ! no longer optimizable to 1.
153+
end function
154+
```
155+
156+
The problem for a compiler is this: at the Fortran language level, no
157+
language construct has the same useful guarantees against aliasing as
158+
dummy arguments have.
159+
A program transformation that changes dummy arguments into something
160+
else needs to implement in its internal or intermediate representations
161+
some kind of metadata that preserves assumptions against aliasing.
162+
163+
### `INTENT(IN)`
164+
165+
A dummy argument may have an`INTENT` attribute.
166+
The relevant case for alias analysis is `INTENT(IN)`, as constraint
167+
C844 prohibits the appearance of an `INTENT(IN)` non-pointer dummy
168+
argument in any "variable definition context" (19.6.7), which is
169+
Fortran's way of saying that it might be at risk of modification.
170+
171+
It would be great if the compiler could assume that an actual argument
172+
that corresponds to an `INTENT(IN)` dummy argument is unchanged after
173+
the called subprogram returns.
174+
Unfortunately, the language has holes that admit ways by which an
175+
`INTENT(IN)` dummy argument may change, even in a conforming program
176+
(paragraph 2 and note 4 in subclause 8.5.10 notwithstanding).
177+
In particular, Fortran nowhere states that a non-pointer `INTENT(IN)`
178+
dummy argument is not "definable".
179+
180+
1. `INTENT(IN)` does not prevent the same variable from also being
181+
associated with another dummy argument in the same call *without*
182+
`INTENT(IN)` and being modified thereby, which is conforming so
183+
long as the subprogram never references the dummy argument that
184+
has `INTENT(IN)`.
185+
In other words, `INTENT(IN)` is necessary but not sufficient to
186+
guarantee safety from modification.
187+
1. A dummy argument may have `INTENT(IN)` and `TARGET` attributes,
188+
and in a non-`PURE` subprogram this would allow modification of
189+
its effective argument by means of a local pointer.
190+
1. An `INTENT(IN)` dummy argument may be forwarded to another
191+
procedure's dummy argument with no `INTENT` attribute, and is
192+
susceptible to being modified during that call.
193+
This case includes references to procedures with implicit
194+
interfaces.
195+
196+
So, for the purposes of use/def/kill analysis, associating a variable with
197+
a non-`PURE` procedure's non-pointer dummy argument may be fraught
198+
even when `INTENT(IN)` is present without `VALUE`.
199+
200+
Arguing the other side of this:
201+
an interoperable procedure's `INTENT(IN)` dummy
202+
arguments are forbidden from being modified, and it would be odd
203+
for calls to foreign C functions to be safer than native calls (18.7).
204+
205+
### `VALUE`
206+
207+
A dummy argument with the `VALUE` attribute is effectively meant to
208+
be copied into a temporary for a call and not copied back into
209+
its original variable (if any).
210+
A `VALUE` dummy argument is therefore as safe from aliasing as
211+
a local variable of the subprogram is.
212+
213+
## Pointers and targets
214+
215+
Modern Fortran's pointers can't associate with arbitrary data.
216+
They can be pointed only at objects that have the explicit `TARGET`
217+
attribute, or at the targets of other pointers.
218+
219+
A variable that does not have the `TARGET` attribute is generally
220+
safe from aliasing with pointers (but see exceptions below).
221+
And generally, pointers must be assumed to alias all other pointers and
222+
all `TARGET` data (perhaps reduced with data flow analysis).
223+
224+
A `VOLATILE` pointer can only point to a `VOLATILE` target, and
225+
a non-`VOLATILE` pointer cannot.
226+
A clever programmer might try to exploit this requirement to
227+
clarify alias analysis, but I have not encountered such usage
228+
so far.
229+
230+
### The `TARGET` hole for dummy arguments
231+
232+
An actual argument that doesn't have the `TARGET` attribute can still be
233+
associated with a dummy argument that *is* a target.
234+
This allows a non-target variable to become a target during the lifetime
235+
of a call.
236+
In a non-`PURE` subprogram (15.7), a pointer may be assigned to such a
237+
dummy argument or to a portion of it.
238+
Such a pointer has a valid lifetime that ends when the subprogram does.
239+
240+
### Valid lifetimes of pointers to dummy arguments
241+
242+
The Fortran standard doesn't mention compiler-generated and -populated
243+
temporary storage in the context of argument association in 15.5.2,
244+
apart from `VALUE`, but instead tries to name all of the circumstances
245+
in which an actual argument's value may have to be transmitted by means
246+
of a temporary in each of the paragraphs that constrain the usable
247+
lifetimes of a pointer that has been pointed to a dummy argument
248+
during a call.
249+
It would be more clear, I think, had the standard simply described
250+
the reasons for which an actual argument might have to occupy temporary
251+
storage, and then just said that pointers to temporaries must not be
252+
used once those temporaries no longer exist.
253+
254+
### Lack of pointer target `INTENT`
255+
256+
`INTENT` attributes for dummy pointer arguments apply to the pointer
257+
itself, not to the data to which the pointer points.
258+
Fortran still has no means of declaring a read-only pointer.
259+
Fortran also has no rule against associating read-only data with a pointer.
260+
261+
### Cray pointers
262+
263+
Cray pointers are, or were, an extension that attempted to provide
264+
some of the capabilities of modern pointers and allocatables before those
265+
features were standardized.
266+
They had some aliasing restrictions; in particular, Cray pointers were
267+
not allowed to alias each other.
268+
269+
They are now more or less obsolete and we have no plan in place to
270+
support them.
271+
272+
## Type considerations
273+
274+
Pointers with distinct types may alias so long as their types are
275+
compatible in the sense of the standard.
276+
277+
Pointers to derived types and `COMPLEX` may alias with pointers to the
278+
types of their components.
279+
For example:
280+
```
281+
complex, pointer :: pz(:)
282+
real, pointer :: pa(:)
283+
pa => z(:)%re ! points to all of the real components
284+
```
285+
286+
### Shape and rank
287+
288+
Array rank is not a material consideration to alias analysis.
289+
Two pointers may alias even if their ranks or shapes differ.
290+
For example, a pointer may associate with a column in a matrix
291+
to which another pointer associates;
292+
or a matrix pointer with only one column or one row may associate
293+
with a vector.
294+
295+
It is also possible in Fortran to "remap" target data by establishing
296+
a pointer of arbitrary rank as a view of a storage sequence.
297+
For example:
298+
```
299+
real, target :: vector(100)
300+
real, pointer :: matrix(:,:)
301+
matrix(1:10,1:10) => v ! now vector's elements look like a matrix
302+
```
303+
304+
## Selectors in `ASSOCIATE`, `SELECT TYPE`, and `CHANGE TEAM`
305+
306+
Selectors in `ASSOCIATE` and related constructs may associate with
307+
either expression values or variables.
308+
In the case of variables, the language imposes no restriction on
309+
aliasing during the lifetime of the construct, and the compiler must
310+
not assume that a selector works in a manner that is analogous to
311+
that of a dummy argument.
312+
313+
## Allocatables
314+
315+
There really isn't anything special about `ALLOCATABLE` objects
316+
from the perspective of aliasing, apart from rules (above) that requiring
317+
`ALLOCATABLE` dummy arguments be (de)allocated only by way of the dummy
318+
argument.
319+
320+
Because an `ALLOCATABLE` dummy argument preserves the values of lower
321+
bounds and can be assumed to be contiguous, some programmers advocate
322+
the use of explicitly `ALLOCATABLE` dummy arguments even when subprograms
323+
do not modify their allocation status.
324+
The usual aliasing restrictions still apply, even when the same `ALLOCATABLE`
325+
is associated with two or more dummy arguments on a call.
326+
327+
## `ASYNCHRONOUS` and `VOLATILE`
328+
329+
These attributes can, unlike any other, be scoped in Fortran by means of
330+
redeclaration in a `BLOCK` construct or nested procedure.
331+
332+
`ASYNCHRONOUS` data must be assumed to be read or written by some other
333+
agent during its lifetime.
334+
For example, Fortran's asynchronous I/O capabilities might be implemented
335+
in a runtime support library by means of threading or explicitly asynchronous
336+
system calls.
337+
An MPI implementation might use `ASYNCHRONOUS` dummy arguments to indicate
338+
that data transfers may take place during program execution in some way that
339+
is not visible to the Fortran compiler.
340+
341+
The optimizer must handle `ASYNCHRONOUS` and `VOLATILE` data with great care.
342+
Reads and writes of `ASYNCHRONOUS` data cannot be moved across statements
343+
that might initiate or complete background operations.
344+
Reads and writes of `VOLATILE` data should be treated like `volatile` in C:
345+
there are no "dead" writes, reads cannot be CSE'd, and both operations should
346+
be properly fenced.
347+
348+
## Storage assocation via `EQUIVALENCE`
349+
350+
A non-allocatable object, or parts of one, may have multiple names in Fortran
351+
via `EQUIVALENCE`.
352+
These objects cannot be have the `POINTER` or `TARGET` attributes.
353+
Their offsets in static, stack, or `COMMON` storage is resolved by semantics
354+
prior to lowering.
355+

0 commit comments

Comments
 (0)