]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgfortran/m4/cshift0.m4
* config/microblaze/microblaze.c (microblaze_expand_block_move): Treat
[thirdparty/gcc.git] / libgfortran / m4 / cshift0.m4
CommitLineData
95f15c5b 1`/* Helper function for cshift functions.
fbd26352 2 Copyright (C) 2008-2019 Free Software Foundation, Inc.
95f15c5b 3 Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
4
553877d9 5This file is part of the GNU Fortran runtime library (libgfortran).
95f15c5b 6
7Libgfortran is free software; you can redistribute it and/or
8modify it under the terms of the GNU General Public
9License as published by the Free Software Foundation; either
6bc9506f 10version 3 of the License, or (at your option) any later version.
95f15c5b 11
12Libgfortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
6bc9506f 17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
95f15c5b 25
26#include "libgfortran.h"
95f15c5b 27#include <string.h>'
28
29include(iparm.m4)dnl
30
31`#if defined (HAVE_'rtype_name`)
32
33void
c75dca49 34cshift0_'rtype_code` ('rtype` *ret, const 'rtype` *array, ptrdiff_t shift,
95f15c5b 35 int which)
36{
37 /* r.* indicates the return array. */
38 index_type rstride[GFC_MAX_DIMENSIONS];
39 index_type rstride0;
40 index_type roffset;
41 'rtype_name` *rptr;
42
43 /* s.* indicates the source array. */
44 index_type sstride[GFC_MAX_DIMENSIONS];
45 index_type sstride0;
46 index_type soffset;
47 const 'rtype_name` *sptr;
48
49 index_type count[GFC_MAX_DIMENSIONS];
50 index_type extent[GFC_MAX_DIMENSIONS];
51 index_type dim;
52 index_type len;
53 index_type n;
54
e6861935 55 bool do_blocked;
56 index_type r_ex, a_ex;
57
95f15c5b 58 which = which - 1;
59 sstride[0] = 0;
60 rstride[0] = 0;
61
62 extent[0] = 1;
63 count[0] = 0;
64 n = 0;
65 /* Initialized for avoiding compiler warnings. */
66 roffset = 1;
67 soffset = 1;
68 len = 0;
69
e6861935 70 r_ex = 1;
71 a_ex = 1;
72
73 if (which > 0)
95f15c5b 74 {
e6861935 75 /* Test if both ret and array are contiguous. */
76 do_blocked = true;
77 dim = GFC_DESCRIPTOR_RANK (array);
78 for (n = 0; n < dim; n ++)
79 {
80 index_type rs, as;
81 rs = GFC_DESCRIPTOR_STRIDE (ret, n);
82 if (rs != r_ex)
83 {
84 do_blocked = false;
85 break;
86 }
87 as = GFC_DESCRIPTOR_STRIDE (array, n);
88 if (as != a_ex)
89 {
90 do_blocked = false;
91 break;
92 }
93 r_ex *= GFC_DESCRIPTOR_EXTENT (ret, n);
94 a_ex *= GFC_DESCRIPTOR_EXTENT (array, n);
95 }
96 }
97 else
98 do_blocked = false;
99
100 n = 0;
101
102 if (do_blocked)
103 {
104 /* For contiguous arrays, use the relationship that
105
106 dimension(n1,n2,n3) :: a, b
107 b = cshift(a,sh,3)
108
109 can be dealt with as if
110
111 dimension(n1*n2*n3) :: an, bn
112 bn = cshift(a,sh*n1*n2,1)
113
114 we can used a more blocked algorithm for dim>1. */
115 sstride[0] = 1;
116 rstride[0] = 1;
117 roffset = 1;
118 soffset = 1;
119 len = GFC_DESCRIPTOR_STRIDE(array, which)
120 * GFC_DESCRIPTOR_EXTENT(array, which);
121 shift *= GFC_DESCRIPTOR_STRIDE(array, which);
122 for (dim = which + 1; dim < GFC_DESCRIPTOR_RANK (array); dim++)
123 {
124 count[n] = 0;
125 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
126 rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
127 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
128 n++;
129 }
130 dim = GFC_DESCRIPTOR_RANK (array) - which;
131 }
132 else
133 {
134 for (dim = 0; dim < GFC_DESCRIPTOR_RANK (array); dim++)
135 {
136 if (dim == which)
137 {
138 roffset = GFC_DESCRIPTOR_STRIDE(ret,dim);
139 if (roffset == 0)
140 roffset = 1;
141 soffset = GFC_DESCRIPTOR_STRIDE(array,dim);
142 if (soffset == 0)
143 soffset = 1;
144 len = GFC_DESCRIPTOR_EXTENT(array,dim);
145 }
146 else
147 {
148 count[n] = 0;
149 extent[n] = GFC_DESCRIPTOR_EXTENT(array,dim);
150 rstride[n] = GFC_DESCRIPTOR_STRIDE(ret,dim);
151 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,dim);
152 n++;
153 }
154 }
155 if (sstride[0] == 0)
156 sstride[0] = 1;
157 if (rstride[0] == 0)
158 rstride[0] = 1;
159
160 dim = GFC_DESCRIPTOR_RANK (array);
95f15c5b 161 }
95f15c5b 162
95f15c5b 163 rstride0 = rstride[0];
164 sstride0 = sstride[0];
553877d9 165 rptr = ret->base_addr;
166 sptr = array->base_addr;
95f15c5b 167
37598f0f 168 /* Avoid the costly modulo for trivially in-bound shifts. */
169 if (shift < 0 || shift >= len)
170 {
171 shift = len == 0 ? 0 : shift % (ptrdiff_t)len;
172 if (shift < 0)
173 shift += len;
174 }
95f15c5b 175
176 while (rptr)
177 {
178 /* Do the shift for this dimension. */
179
180 /* If elements are contiguous, perform the operation
181 in two block moves. */
182 if (soffset == 1 && roffset == 1)
183 {
184 size_t len1 = shift * sizeof ('rtype_name`);
185 size_t len2 = (len - shift) * sizeof ('rtype_name`);
186 memcpy (rptr, sptr + shift, len2);
187 memcpy (rptr + (len - shift), sptr, len1);
188 }
189 else
190 {
191 /* Otherwise, we will have to perform the copy one element at
192 a time. */
193 'rtype_name` *dest = rptr;
194 const 'rtype_name` *src = &sptr[shift * soffset];
195
196 for (n = 0; n < len - shift; n++)
197 {
198 *dest = *src;
199 dest += roffset;
200 src += soffset;
201 }
202 for (src = sptr, n = 0; n < shift; n++)
203 {
204 *dest = *src;
205 dest += roffset;
206 src += soffset;
207 }
208 }
209
210 /* Advance to the next section. */
211 rptr += rstride0;
212 sptr += sstride0;
213 count[0]++;
214 n = 0;
215 while (count[n] == extent[n])
216 {
217 /* When we get to the end of a dimension, reset it and increment
218 the next dimension. */
219 count[n] = 0;
220 /* We could precalculate these products, but this is a less
221 frequently used path so probably not worth it. */
222 rptr -= rstride[n] * extent[n];
223 sptr -= sstride[n] * extent[n];
224 n++;
225 if (n >= dim - 1)
226 {
227 /* Break out of the loop. */
228 rptr = NULL;
229 break;
230 }
231 else
232 {
233 count[n]++;
234 rptr += rstride[n];
235 sptr += sstride[n];
236 }
237 }
238 }
239
240 return;
241}
242
243#endif'