annotate flang/docs/ArrayComposition.md @ 223:5f17cb93ff66 llvm-original

LLVM13 (2021/7/18)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 18 Jul 2021 22:43:00 +0900
parents 79ff65ed7e25
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 <!--===- docs/ArrayComposition.md
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
2
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 See https://llvm.org/LICENSE.txt for license information.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 -->
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 # Array Composition
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 ```eval_rst
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 .. contents::
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 :local:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 This note attempts to describe the motivation for and design of an
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 implementation of Fortran 90 (and later) array expression evaluation that
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 minimizes the use of dynamically allocated temporary storage for
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 the results of calls to transformational intrinsic functions, and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 making them more amenable to acceleration.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
21
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 The transformational intrinsic functions of Fortran of interest to
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 us here include:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
24
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 * Reductions to scalars (`SUM(X)`, also `ALL`, `ANY`, `COUNT`,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 `DOT_PRODUCT`,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 `IALL`, `IANY`, `IPARITY`, `MAXVAL`, `MINVAL`, `PARITY`, `PRODUCT`)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 * Axial reductions (`SUM(X,DIM=)`, &c.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 * Location reductions to indices (`MAXLOC`, `MINLOC`, `FINDLOC`)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 * Axial location reductions (`MAXLOC(DIM=`, &c.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 * `TRANSPOSE(M)` matrix transposition
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 * `RESHAPE` without `ORDER=`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 * `RESHAPE` with `ORDER=`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 * `CSHIFT` and `EOSHIFT` with scalar `SHIFT=`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 * `CSHIFT` and `EOSHIFT` with array-valued `SHIFT=`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 * `PACK` and `UNPACK`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 * `MATMUL`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 * `SPREAD`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 Other Fortran intrinsic functions are technically transformational (e.g.,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 `COMMAND_ARGUMENT_COUNT`) but not of interest for this note.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 The generic `REDUCE` is also not considered here.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
43
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 ## Arrays as functions
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 A whole array can be viewed as a function that maps its indices to the values
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 of its elements.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 Specifically, it is a map from a tuple of integers to its element type.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 The rank of the array is the number of elements in that tuple,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 and the shape of the array delimits the domain of the map.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
51
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 `REAL :: A(N,M)` can be seen as a function mapping ordered pairs of integers
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 `(J,K)` with `1<=J<=N` and `1<=J<=M` to real values.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
54
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 ## Array expressions as functions
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
56
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 The same perspective can be taken of an array expression comprising
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 intrinsic operators and elemental functions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 Fortran doesn't allow one to apply subscripts directly to an expression,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 but expressions have rank and shape, and one can view array expressions
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 as functions over index tuples by applying those indices to the arrays
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 and subexpressions in the expression.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 Consider `B = A + 1.0` (assuming `REAL :: A(N,M), B(N,M)`).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 The right-hand side of that assignment could be evaluated into a
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 temporary array `T` and then subscripted as it is copied into `B`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 REAL, ALLOCATABLE :: T(:,:)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 ALLOCATE(T(N,M))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 DO CONCURRENT(J=1:N,K=1:M)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 T(J,K)=A(J,K) + 1.0
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 END DO
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 DO CONCURRENT(J=1:N,K=1:M)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 B(J,K)=T(J,K)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 END DO
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 DEALLOCATE(T)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 But we can avoid the allocation, population, and deallocation of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 the temporary by treating the right-hand side expression as if it
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 were a statement function `F(J,K)=A(J,K)+1.0` and evaluating
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 DO CONCURRENT(J=1:N,K=1:M)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 A(J,K)=F(J,K)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 END DO
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
86
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 In general, when a Fortran array assignment to a non-allocatable array
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 does not include the left-hand
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 side variable as an operand of the right-hand side expression, and any
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 function calls on the right-hand side are elemental or scalar-valued,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 we can avoid the use of a temporary.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
92
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 ## Transformational intrinsic functions as function composition
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
94
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 Many of the transformational intrinsic functions listed above
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 can, when their array arguments are viewed as functions over their
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 index tuples, be seen as compositions of those functions with
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 functions of the "incoming" indices -- yielding a function for
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 an entire right-hand side of an array assignment statement.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
100
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 For example, the application of `TRANSPOSE(A + 1.0)` to the index
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 tuple `(J,K)` becomes `A(K,J) + 1.0`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
103
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 Partial (axial) reductions can be similarly composed.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 The application of `SUM(A,DIM=2)` to the index `J` is the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 complete reduction `SUM(A(J,:))`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
107
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 More completely:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 * Reductions to scalars (`SUM(X)` without `DIM=`) become
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 runtime calls; the result needs no dynamic allocation,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 being a scalar.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 * Axial reductions (`SUM(X,DIM=d)`) applied to indices `(J,K)`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 become scalar values like `SUM(X(J,K,:))` if `d=3`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 * Location reductions to indices (`MAXLOC(X)` without `DIM=`)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 do not require dynamic allocation, since their results are
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 either scalar or small vectors of length `RANK(X)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 * Axial location reductions (`MAXLOC(X,DIM=)`, &c.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 are handled like other axial reductions like `SUM(DIM=)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 * `TRANSPOSE(M)` exchanges the two components of the index tuple.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 * `RESHAPE(A,SHAPE=s)` without `ORDER=` must precompute the shape
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 vector `S`, and then use it to linearize indices into offsets
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 in the storage order of `A` (whose shape must also be captured).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 These conversions can involve division and/or modulus, which
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 can be optimized into a fixed-point multiplication using the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 usual technique.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 * `RESHAPE` with `ORDER=` is similar, but must permute the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 components of the index tuple; it generalizes `TRANSPOSE`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 * `CSHIFT` applies addition and modulus.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 * `EOSHIFT` applies addition and a conditional move (`MERGE`).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 * `PACK` and `UNPACK` are likely to require a runtime call.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 * `MATMUL(A,B)` can become `DOT_PRODUCT(A(J,:),B(:,K))`, but
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 might benefit from calling a highly optimized runtime
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 routine.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 * `SPREAD(A,DIM=d,NCOPIES=n)` for compile-time `d` simply
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 applies `A` to a reduced index tuple.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
136
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 ## Determination of rank and shape
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
138
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 An important part of evaluating array expressions without the use of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 temporary storage is determining the shape of the result prior to,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 or without, evaluating the elements of the result.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 The shapes of array objects, results of elemental intrinsic functions,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 and results of intrinsic operations are obvious.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 But it is possible to determine the shapes of the results of many
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 transformational intrinsic function calls as well.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
147
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 * `SHAPE(SUM(X,DIM=d))` is `SHAPE(X)` with one element removed:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 `PACK(SHAPE(X),[(j,j=1,RANK(X))]/=d)` in general.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 (The `DIM=` argument is commonly a compile-time constant.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 * `SHAPE(MAXLOC(X))` is `[RANK(X)]`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 * `SHAPE(MAXLOC(X,DIM=d))` is `SHAPE(X)` with one element removed.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 * `SHAPE(TRANSPOSE(M))` is a reversal of `SHAPE(M)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 * `SHAPE(RESHAPE(..., SHAPE=S))` is `S`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 * `SHAPE(CSHIFT(X))` is `SHAPE(X)`; same with `EOSHIFT`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 * `SHAPE(PACK(A,VECTOR=V))` is `SHAPE(V)`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 * `SHAPE(PACK(A,MASK=m))` with non-scalar `m` and without `VECTOR=` is `[COUNT(m)]`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 * `RANK(PACK(...))` is always 1.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 * `SHAPE(UNPACK(MASK=M))` is `SHAPE(M)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 * `SHAPE(MATMUL(A,B))` drops one value from `SHAPE(A)` and another from `SHAPE(B)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 * `SHAPE(SHAPE(X))` is `[RANK(X)]`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 * `SHAPE(SPREAD(A,DIM=d,NCOPIES=n))` is `SHAPE(A)` with `n` inserted at
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 dimension `d`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
164
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 This is useful because expression evaluations that *do* require temporaries
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 to hold their results (due to the context in which the evaluation occurs)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 can be implemented with a separation of the allocation
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 of the temporary array and the population of the array.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 The code that evaluates the expression, or that implements a transformational
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 intrinsic in the runtime library, can be designed with an API that includes
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 a pointer to the destination array as an argument.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
172
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 Statements like `ALLOCATE(A,SOURCE=expression)` should thus be capable
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 of evaluating their array expressions directly into the newly-allocated
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 storage for the allocatable array.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 The implementation would generate code to calculate the shape, use it
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 to allocate the memory and populate the descriptor, and then drive a
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 loop nest around the expression to populate the array.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 In cases where the analyzed shape is known at compile time, we should
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 be able to have the opportunity to avoid heap allocation in favor of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 stack storage, if the scope of the variable is local.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
182
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 ## Automatic reallocation of allocatables
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
184
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 Fortran 2003 introduced the ability to assign non-conforming array expressions
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 to ALLOCATABLE arrays with the implied semantics of reallocation to the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 new shape.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 The implementation of this feature also becomes more straightforward if
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 our implementation of array expressions has decoupled calculation of shapes
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 from the evaluation of the elements of the result.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
191
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 ## Rewriting rules
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
193
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 Let `{...}` denote an ordered tuple of 1-based indices, e.g. `{j,k}`, into
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 the result of an array expression or subexpression.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
196
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 * Array constructors always yield vectors; higher-rank arrays that appear as
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 constituents are flattened; so `[X] => RESHAPE(X,SHAPE=[SIZE(X)})`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 * Array constructors with multiple constituents are concatenations of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 their constituents; so `[X,Y]{j} => MERGE(Y{j-SIZE(X)},X{j},J>SIZE(X))`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 * Array constructors with implied DO loops are difficult when nested
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 triangularly.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 * Whole array references can have lower bounds other than 1, so
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 `A => A(LBOUND(A,1):UBOUND(A,1),...)`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 * Array sections simply apply indices: `A(i:...:n){j} => A(i1+n*(j-1))`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 * Vector-valued subscripts apply indices to the subscript: `A(N(:)){j} => A(N(:){j})`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 * Scalar operands ignore indices: `X{j,k} => X`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 Further, they are evaluated at most once.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 * Elemental operators and functions apply indices to their arguments:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 `(A(:,:) + B(:,:)){j,k}` => A(:,:){j,k} + B(:,:){j,k}`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 * `TRANSPOSE(X){j,k} => X{k,j}`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 * `SPREAD(X,DIM=2,...){j,k} => X{j}`; i.e., the contents are replicated.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 If X is sufficiently expensive to compute elementally, it might be evaluated
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 into a temporary.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
215
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 (more...)