|
| 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