modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/pr28982a.c (about)

     1  /* PR rtl-optimization/28982.  Function foo() does the equivalent of:
     2  
     3       float tmp_results[NVARS];
     4       for (int i = 0; i < NVARS; i++)
     5         {
     6  	 int inc = incs[i];
     7  	 float *ptr = ptrs[i], result = 0;
     8  	 for (int j = 0; j < n; j++)
     9  	   result += *ptr, ptr += inc;
    10  	 tmp_results[i] = result;
    11         }
    12       memcpy (results, tmp_results, sizeof (results));
    13  
    14     but without the outermost loop.  The idea is to create high register
    15     pressure and ensure that some INC and PTR variables are spilled.
    16  
    17     On ARM targets, sequences like "result += *ptr, ptr += inc" can
    18     usually be implemented using (mem (post_modify ...)), and we do
    19     indeed create such MEMs before reload for this testcase.  However,
    20     (post_modify ...) is not a valid address for coprocessor loads, so
    21     for -mfloat-abi=softfp, reload reloads the POST_MODIFY into a base
    22     register.  GCC did not deal correctly with cases where the base and
    23     index of the POST_MODIFY are themselves reloaded.  */
    24  #define NITER 4
    25  #define NVARS 20
    26  #define MULTI(X) \
    27    X( 0), X( 1), X( 2), X( 3), X( 4), X( 5), X( 6), X( 7), X( 8), X( 9), \
    28    X(10), X(11), X(12), X(13), X(14), X(15), X(16), X(17), X(18), X(19)
    29  
    30  #define DECLAREI(INDEX) inc##INDEX = incs[INDEX]
    31  #define DECLAREF(INDEX) *ptr##INDEX = ptrs[INDEX], result##INDEX = 0
    32  #define LOOP(INDEX) result##INDEX += *ptr##INDEX, ptr##INDEX += inc##INDEX
    33  #define COPYOUT(INDEX) results[INDEX] = result##INDEX
    34  
    35  float *ptrs[NVARS];
    36  float results[NVARS];
    37  int incs[NVARS];
    38  
    39  void __attribute__((noinline))
    40  foo (int n)
    41  {
    42    int MULTI (DECLAREI);
    43    float MULTI (DECLAREF);
    44    while (n--)
    45      MULTI (LOOP);
    46    MULTI (COPYOUT);
    47  }
    48  
    49  float input[NITER * NVARS];
    50  
    51  int
    52  main (void)
    53  {
    54    int i;
    55  
    56    for (i = 0; i < NVARS; i++)
    57      ptrs[i] = input + i, incs[i] = i;
    58    for (i = 0; i < NITER * NVARS; i++)
    59      input[i] = i;
    60    foo (NITER);
    61    for (i = 0; i < NVARS; i++)
    62      if (results[i] != i * NITER * (NITER + 1) / 2)
    63        return 1;
    64    return 0;
    65  }