tree-optimization/113385 - wrong loop father with early exit vectorization
[official-gcc.git] / libgfortran / generated / maxloc1_16_i4.c
blob3facff476bd5754ff2fb5da004f9a9302b46547e
1 /* Implementation of the MAXLOC intrinsic
2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
27 #include <assert.h>
30 #if defined (HAVE_GFC_INTEGER_4) && defined (HAVE_GFC_INTEGER_16)
32 #define HAVE_BACK_ARG 1
35 extern void maxloc1_16_i4 (gfc_array_i16 * const restrict,
36 gfc_array_i4 * const restrict, const index_type * const restrict, GFC_LOGICAL_4 back);
37 export_proto(maxloc1_16_i4);
39 void
40 maxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
41 gfc_array_i4 * const restrict array,
42 const index_type * const restrict pdim, GFC_LOGICAL_4 back)
44 index_type count[GFC_MAX_DIMENSIONS];
45 index_type extent[GFC_MAX_DIMENSIONS];
46 index_type sstride[GFC_MAX_DIMENSIONS];
47 index_type dstride[GFC_MAX_DIMENSIONS];
48 const GFC_INTEGER_4 * restrict base;
49 GFC_INTEGER_16 * restrict dest;
50 index_type rank;
51 index_type n;
52 index_type len;
53 index_type delta;
54 index_type dim;
55 int continue_loop;
57 /* Make dim zero based to avoid confusion. */
58 rank = GFC_DESCRIPTOR_RANK (array) - 1;
59 dim = (*pdim) - 1;
61 if (unlikely (dim < 0 || dim > rank))
63 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
64 "is %ld, should be between 1 and %ld",
65 (long int) dim + 1, (long int) rank + 1);
68 len = GFC_DESCRIPTOR_EXTENT(array,dim);
69 if (len < 0)
70 len = 0;
71 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
73 for (n = 0; n < dim; n++)
75 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
76 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
78 if (extent[n] < 0)
79 extent[n] = 0;
81 for (n = dim; n < rank; n++)
83 sstride[n] = GFC_DESCRIPTOR_STRIDE(array, n + 1);
84 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
86 if (extent[n] < 0)
87 extent[n] = 0;
90 if (retarray->base_addr == NULL)
92 size_t alloc_size, str;
94 for (n = 0; n < rank; n++)
96 if (n == 0)
97 str = 1;
98 else
99 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
101 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
105 retarray->offset = 0;
106 retarray->dtype.rank = rank;
108 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
110 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
111 if (alloc_size == 0)
112 return;
114 else
116 if (rank != GFC_DESCRIPTOR_RANK (retarray))
117 runtime_error ("rank of return array incorrect in"
118 " MAXLOC intrinsic: is %ld, should be %ld",
119 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
120 (long int) rank);
122 if (unlikely (compile_options.bounds_check))
123 bounds_ifunction_return ((array_t *) retarray, extent,
124 "return value", "MAXLOC");
127 for (n = 0; n < rank; n++)
129 count[n] = 0;
130 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
131 if (extent[n] <= 0)
132 return;
135 base = array->base_addr;
136 dest = retarray->base_addr;
138 continue_loop = 1;
139 while (continue_loop)
141 const GFC_INTEGER_4 * restrict src;
142 GFC_INTEGER_16 result;
143 src = base;
146 GFC_INTEGER_4 maxval;
147 #if defined (GFC_INTEGER_4_INFINITY)
148 maxval = -GFC_INTEGER_4_INFINITY;
149 #else
150 maxval = (-GFC_INTEGER_4_HUGE-1);
151 #endif
152 result = 1;
153 if (len <= 0)
154 *dest = 0;
155 else
157 #if ! defined HAVE_BACK_ARG
158 for (n = 0; n < len; n++, src += delta)
160 #endif
162 #if defined (GFC_INTEGER_4_QUIET_NAN)
163 for (n = 0; n < len; n++, src += delta)
165 if (*src >= maxval)
167 maxval = *src;
168 result = (GFC_INTEGER_16)n + 1;
169 break;
172 #else
173 n = 0;
174 #endif
175 for (; n < len; n++, src += delta)
177 if (back ? *src >= maxval : *src > maxval)
179 maxval = *src;
180 result = (GFC_INTEGER_16)n + 1;
184 *dest = result;
187 /* Advance to the next element. */
188 count[0]++;
189 base += sstride[0];
190 dest += dstride[0];
191 n = 0;
192 while (count[n] == extent[n])
194 /* When we get to the end of a dimension, reset it and increment
195 the next dimension. */
196 count[n] = 0;
197 /* We could precalculate these products, but this is a less
198 frequently used path so probably not worth it. */
199 base -= sstride[n] * extent[n];
200 dest -= dstride[n] * extent[n];
201 n++;
202 if (n >= rank)
204 /* Break out of the loop. */
205 continue_loop = 0;
206 break;
208 else
210 count[n]++;
211 base += sstride[n];
212 dest += dstride[n];
219 extern void mmaxloc1_16_i4 (gfc_array_i16 * const restrict,
220 gfc_array_i4 * const restrict, const index_type * const restrict,
221 gfc_array_l1 * const restrict, GFC_LOGICAL_4 back);
222 export_proto(mmaxloc1_16_i4);
224 void
225 mmaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
226 gfc_array_i4 * const restrict array,
227 const index_type * const restrict pdim,
228 gfc_array_l1 * const restrict mask, GFC_LOGICAL_4 back)
230 index_type count[GFC_MAX_DIMENSIONS];
231 index_type extent[GFC_MAX_DIMENSIONS];
232 index_type sstride[GFC_MAX_DIMENSIONS];
233 index_type dstride[GFC_MAX_DIMENSIONS];
234 index_type mstride[GFC_MAX_DIMENSIONS];
235 GFC_INTEGER_16 * restrict dest;
236 const GFC_INTEGER_4 * restrict base;
237 const GFC_LOGICAL_1 * restrict mbase;
238 index_type rank;
239 index_type dim;
240 index_type n;
241 index_type len;
242 index_type delta;
243 index_type mdelta;
244 int mask_kind;
246 if (mask == NULL)
248 #ifdef HAVE_BACK_ARG
249 maxloc1_16_i4 (retarray, array, pdim, back);
250 #else
251 maxloc1_16_i4 (retarray, array, pdim);
252 #endif
253 return;
256 dim = (*pdim) - 1;
257 rank = GFC_DESCRIPTOR_RANK (array) - 1;
260 if (unlikely (dim < 0 || dim > rank))
262 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
263 "is %ld, should be between 1 and %ld",
264 (long int) dim + 1, (long int) rank + 1);
267 len = GFC_DESCRIPTOR_EXTENT(array,dim);
268 if (len < 0)
269 len = 0;
271 mbase = mask->base_addr;
273 mask_kind = GFC_DESCRIPTOR_SIZE (mask);
275 if (mask_kind == 1 || mask_kind == 2 || mask_kind == 4 || mask_kind == 8
276 #ifdef HAVE_GFC_LOGICAL_16
277 || mask_kind == 16
278 #endif
280 mbase = GFOR_POINTER_TO_L1 (mbase, mask_kind);
281 else
282 runtime_error ("Funny sized logical array");
284 delta = GFC_DESCRIPTOR_STRIDE(array,dim);
285 mdelta = GFC_DESCRIPTOR_STRIDE_BYTES(mask,dim);
287 for (n = 0; n < dim; n++)
289 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n);
290 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask,n);
291 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
293 if (extent[n] < 0)
294 extent[n] = 0;
297 for (n = dim; n < rank; n++)
299 sstride[n] = GFC_DESCRIPTOR_STRIDE(array,n + 1);
300 mstride[n] = GFC_DESCRIPTOR_STRIDE_BYTES(mask, n + 1);
301 extent[n] = GFC_DESCRIPTOR_EXTENT(array, n + 1);
303 if (extent[n] < 0)
304 extent[n] = 0;
307 if (retarray->base_addr == NULL)
309 size_t alloc_size, str;
311 for (n = 0; n < rank; n++)
313 if (n == 0)
314 str = 1;
315 else
316 str= GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
318 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
322 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
324 retarray->offset = 0;
325 retarray->dtype.rank = rank;
327 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
328 if (alloc_size == 0)
329 return;
331 else
333 if (rank != GFC_DESCRIPTOR_RANK (retarray))
334 runtime_error ("rank of return array incorrect in MAXLOC intrinsic");
336 if (unlikely (compile_options.bounds_check))
338 bounds_ifunction_return ((array_t *) retarray, extent,
339 "return value", "MAXLOC");
340 bounds_equal_extents ((array_t *) mask, (array_t *) array,
341 "MASK argument", "MAXLOC");
345 for (n = 0; n < rank; n++)
347 count[n] = 0;
348 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
349 if (extent[n] <= 0)
350 return;
353 dest = retarray->base_addr;
354 base = array->base_addr;
356 while (base)
358 const GFC_INTEGER_4 * restrict src;
359 const GFC_LOGICAL_1 * restrict msrc;
360 GFC_INTEGER_16 result;
361 src = base;
362 msrc = mbase;
365 GFC_INTEGER_4 maxval;
366 #if defined (GFC_INTEGER_4_INFINITY)
367 maxval = -GFC_INTEGER_4_INFINITY;
368 #else
369 maxval = (-GFC_INTEGER_4_HUGE-1);
370 #endif
371 #if defined (GFC_INTEGER_4_QUIET_NAN)
372 GFC_INTEGER_16 result2 = 0;
373 #endif
374 result = 0;
375 for (n = 0; n < len; n++, src += delta, msrc += mdelta)
378 if (*msrc)
380 #if defined (GFC_INTEGER_4_QUIET_NAN)
381 if (!result2)
382 result2 = (GFC_INTEGER_16)n + 1;
383 if (*src >= maxval)
384 #endif
386 maxval = *src;
387 result = (GFC_INTEGER_16)n + 1;
388 break;
392 #if defined (GFC_INTEGER_4_QUIET_NAN)
393 if (unlikely (n >= len))
394 result = result2;
395 else
396 #endif
397 if (back)
398 for (; n < len; n++, src += delta, msrc += mdelta)
400 if (*msrc && unlikely (*src >= maxval))
402 maxval = *src;
403 result = (GFC_INTEGER_16)n + 1;
406 else
407 for (; n < len; n++, src += delta, msrc += mdelta)
409 if (*msrc && unlikely (*src > maxval))
411 maxval = *src;
412 result = (GFC_INTEGER_16)n + 1;
415 *dest = result;
417 /* Advance to the next element. */
418 count[0]++;
419 base += sstride[0];
420 mbase += mstride[0];
421 dest += dstride[0];
422 n = 0;
423 while (count[n] == extent[n])
425 /* When we get to the end of a dimension, reset it and increment
426 the next dimension. */
427 count[n] = 0;
428 /* We could precalculate these products, but this is a less
429 frequently used path so probably not worth it. */
430 base -= sstride[n] * extent[n];
431 mbase -= mstride[n] * extent[n];
432 dest -= dstride[n] * extent[n];
433 n++;
434 if (n >= rank)
436 /* Break out of the loop. */
437 base = NULL;
438 break;
440 else
442 count[n]++;
443 base += sstride[n];
444 mbase += mstride[n];
445 dest += dstride[n];
452 extern void smaxloc1_16_i4 (gfc_array_i16 * const restrict,
453 gfc_array_i4 * const restrict, const index_type * const restrict,
454 GFC_LOGICAL_4 *, GFC_LOGICAL_4 back);
455 export_proto(smaxloc1_16_i4);
457 void
458 smaxloc1_16_i4 (gfc_array_i16 * const restrict retarray,
459 gfc_array_i4 * const restrict array,
460 const index_type * const restrict pdim,
461 GFC_LOGICAL_4 * mask, GFC_LOGICAL_4 back)
463 index_type count[GFC_MAX_DIMENSIONS];
464 index_type extent[GFC_MAX_DIMENSIONS];
465 index_type dstride[GFC_MAX_DIMENSIONS];
466 GFC_INTEGER_16 * restrict dest;
467 index_type rank;
468 index_type n;
469 index_type dim;
472 if (mask == NULL || *mask)
474 #ifdef HAVE_BACK_ARG
475 maxloc1_16_i4 (retarray, array, pdim, back);
476 #else
477 maxloc1_16_i4 (retarray, array, pdim);
478 #endif
479 return;
481 /* Make dim zero based to avoid confusion. */
482 dim = (*pdim) - 1;
483 rank = GFC_DESCRIPTOR_RANK (array) - 1;
485 if (unlikely (dim < 0 || dim > rank))
487 runtime_error ("Dim argument incorrect in MAXLOC intrinsic: "
488 "is %ld, should be between 1 and %ld",
489 (long int) dim + 1, (long int) rank + 1);
492 for (n = 0; n < dim; n++)
494 extent[n] = GFC_DESCRIPTOR_EXTENT(array,n);
496 if (extent[n] <= 0)
497 extent[n] = 0;
500 for (n = dim; n < rank; n++)
502 extent[n] =
503 GFC_DESCRIPTOR_EXTENT(array,n + 1);
505 if (extent[n] <= 0)
506 extent[n] = 0;
509 if (retarray->base_addr == NULL)
511 size_t alloc_size, str;
513 for (n = 0; n < rank; n++)
515 if (n == 0)
516 str = 1;
517 else
518 str = GFC_DESCRIPTOR_STRIDE(retarray,n-1) * extent[n-1];
520 GFC_DIMENSION_SET(retarray->dim[n], 0, extent[n] - 1, str);
524 retarray->offset = 0;
525 retarray->dtype.rank = rank;
527 alloc_size = GFC_DESCRIPTOR_STRIDE(retarray,rank-1) * extent[rank-1];
529 retarray->base_addr = xmallocarray (alloc_size, sizeof (GFC_INTEGER_16));
530 if (alloc_size == 0)
531 return;
533 else
535 if (rank != GFC_DESCRIPTOR_RANK (retarray))
536 runtime_error ("rank of return array incorrect in"
537 " MAXLOC intrinsic: is %ld, should be %ld",
538 (long int) (GFC_DESCRIPTOR_RANK (retarray)),
539 (long int) rank);
541 if (unlikely (compile_options.bounds_check))
543 for (n=0; n < rank; n++)
545 index_type ret_extent;
547 ret_extent = GFC_DESCRIPTOR_EXTENT(retarray,n);
548 if (extent[n] != ret_extent)
549 runtime_error ("Incorrect extent in return value of"
550 " MAXLOC intrinsic in dimension %ld:"
551 " is %ld, should be %ld", (long int) n + 1,
552 (long int) ret_extent, (long int) extent[n]);
557 for (n = 0; n < rank; n++)
559 count[n] = 0;
560 dstride[n] = GFC_DESCRIPTOR_STRIDE(retarray,n);
563 dest = retarray->base_addr;
565 while(1)
567 *dest = 0;
568 count[0]++;
569 dest += dstride[0];
570 n = 0;
571 while (count[n] == extent[n])
573 /* When we get to the end of a dimension, reset it and increment
574 the next dimension. */
575 count[n] = 0;
576 /* We could precalculate these products, but this is a less
577 frequently used path so probably not worth it. */
578 dest -= dstride[n] * extent[n];
579 n++;
580 if (n >= rank)
581 return;
582 else
584 count[n]++;
585 dest += dstride[n];
591 #endif