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 35float *ptrs[NVARS]; 36float results[NVARS]; 37int incs[NVARS]; 38 39void __attribute__((noinline)) 40foo (int n) 41{ 42 int MULTI (DECLAREI); 43 float MULTI (DECLAREF); 44 while (n--) 45 MULTI (LOOP); 46 MULTI (COPYOUT); 47} 48 49float input[NITER * NVARS]; 50 51int 52main (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} 66