(root)/
glibc-2.38/
include/
loop_unroll.h
       1  /* Macro for explicit loop unrolling.
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _LOOP_UNROLL_H
      20  #define _LOOP_UNROLL_H
      21  
      22  /* Loop unroll macro to be used for explicit force loop unrolling with a
      23     configurable number of iterations.  The idea is to make the loop unrolling
      24     independent of whether the compiler is able to unroll through specific
      25     optimizations options (-funroll-loops or -funroll-all-loops).
      26  
      27     For instance, to implement strcpy with SRC being the source input and
      28     DEST the destination buffer, it is expected the macro to be used in this
      29     way:
      30  
      31       #define ITERATION(index)	\
      32         ({ char c = *str++; *dest++ = c; c != '\0' })
      33  
      34       while (1)
      35         UNROLL_REPEAT (4, ITERATION)
      36  
      37     The loop will be manually unrolled 4 times.  Another option is to do
      38     the index update after the tests:
      39  
      40       #define ITERATION(index)	\
      41         ({ char c = *(str + index); *(dest + index) = c; c != '\0' })
      42       #define UPDATE(n)		\
      43         str += n; dst += n
      44  
      45       while (1)
      46         UNROLL_REPEAT_UPDATE (4, ITERATION, UPDATE)
      47  
      48     The loop will be manually unrolled 4 times and the SRC and DEST pointers
      49     will be updated only after the last iteration.
      50  
      51     Currently, both macros unroll the loop 8 times at maximum.  */
      52  
      53  #define UNROLL_REPEAT_1(X)    if (!X(0)) break;
      54  #define UNROLL_REPEAT_2(X)    UNROLL_REPEAT_1 (X) if (!X (1)) break;
      55  #define UNROLL_REPEAT_3(X)    UNROLL_REPEAT_2 (X) if (!X (2)) break;
      56  #define UNROLL_REPEAT_4(X)    UNROLL_REPEAT_3 (X) if (!X (3)) break;
      57  #define UNROLL_REPEAT_5(X)    UNROLL_REPEAT_4 (X) if (!X (4)) break;
      58  #define UNROLL_REPEAT_6(X)    UNROLL_REPEAT_5 (X) if (!X (5)) break;
      59  #define UNROLL_REPEAT_7(X)    UNROLL_REPEAT_6 (X) if (!X (6)) break;
      60  #define UNROLL_REPEAT_8(X)    UNROLL_REPEAT_7 (X) if (!X (7)) break;
      61  
      62  #define UNROLL_EXPAND(...)    __VA_ARGS__
      63  
      64  #define UNROLL_REPEAT__(N, X) UNROLL_EXPAND(UNROLL_REPEAT_ ## N) (X)
      65  #define UNROLL_REPEAT_(N, X)  UNROLL_REPEAT__ (N, X)
      66  
      67  #define UNROLL_REPEAT(N, X)                \
      68    (void) ({                                \
      69      UNROLL_REPEAT_ (UNROLL_EXPAND(N), X);  \
      70    })
      71  
      72  #define UNROLL_REPEAT_UPDATE(N, X, U)      \
      73    (void) ({                                \
      74      UNROLL_REPEAT_ (UNROLL_EXPAND(N), X);  \
      75      UPDATE (N);                            \
      76    })
      77  
      78  #endif