Add JetStream to PerformanceTests
[WebKit-https.git] / PerformanceTests / JetStream / simple / gcc-loops.cpp
1 #include <sys/time.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <iostream>
6 #include <vector>
7 #include <numeric>
8
9 /// This test contains some of the loops from the GCC vectrorizer example page [1].
10 /// Dorit Nuzman who developed the gcc vectorizer said that we can use them in our test suite.
11 ///
12 /// [1] - http://gcc.gnu.org/projects/tree-ssa/vectorization.html
13
14 #define N 1024
15 #define M 32
16 #define K 4
17 #define ALIGNED16 __attribute__((aligned(16)))
18
19 unsigned short usa[N];
20 short sa[N];
21 short sb[N];
22 short sc[N];
23 unsigned int   ua[N];
24 int   ia[N] ALIGNED16;
25 int   ib[N] ALIGNED16;
26 int   ic[N] ALIGNED16;
27 unsigned int ub[N];
28 unsigned int uc[N];
29 float fa[N], fb[N];
30 float da[N], db[N], dc[N], dd[N];
31 int dj[N];
32
33 struct A {
34   int ca[N];
35 } s;
36
37 int a[N*2] ALIGNED16;
38 int b[N*2] ALIGNED16;
39 int c[N*2] ALIGNED16;
40 int d[N*2] ALIGNED16;
41
42 __attribute__((noinline))
43 void example1 () {
44   int i;
45
46   for (i=0; i<256; i++){
47     a[i] = b[i] + c[i];
48   }
49 }
50
51 __attribute__((noinline))
52 void example2a (int n, int x) {
53    int i;
54
55    /* feature: support for unknown loop bound  */
56    /* feature: support for loop invariants  */
57    for (i=0; i<n; i++) {
58       b[i] = x;
59    }
60 }
61
62 __attribute__((noinline))
63 void example2b (int n, int x) {
64   int i = 0;
65    /* feature: general loop exit condition  */
66    /* feature: support for bitwise operations  */
67    while (n--){
68       a[i] = b[i]&c[i]; i++;
69    }
70 }
71
72
73 typedef int aint __attribute__ ((__aligned__(16)));
74 __attribute__((noinline))
75 void example3 (int n, aint * __restrict__ p, aint * __restrict q) {
76
77    /* feature: support for (aligned) pointer accesses.  */
78    while (n--){
79       *p++ = *q++;
80    }
81 }
82
83 __attribute__((noinline))
84 void example4a (int n, aint * __restrict__ p, aint * __restrict__ q) {
85    /* feature: support for (aligned) pointer accesses  */
86    /* feature: support for constants  */
87    while (n--){
88       *p++ = *q++ + 5;
89    }
90 }
91
92 __attribute__((noinline))
93 void example4b (int n, aint * __restrict__ p, aint * __restrict__ q) {
94    int i;
95
96    /* feature: support for read accesses with a compile time known misalignment  */
97    for (i=0; i<n; i++){
98       a[i] = b[i+1] + c[i+3];
99    }
100 }
101
102 __attribute__((noinline))
103 void example4c (int n, aint * __restrict__ p, aint * __restrict__ q) {
104    int i;
105     const int MAX = 4;
106    /* feature: support for if-conversion  */
107    for (i=0; i<n; i++){
108       int j = a[i];
109       b[i] = (j > MAX ? MAX : 0);
110    }
111 }
112
113 __attribute__((noinline))
114 void  example5 (int n, struct A *s) {
115   int i;
116   for (i = 0; i < n; i++) {
117     /* feature: support for alignable struct access  */
118     s->ca[i] = 5;
119   }
120 }
121
122 __attribute__((noinline))
123 void  example7 (int x) {
124    int i;
125
126    /* feature: support for read accesses with an unknown misalignment  */
127    for (i=0; i<N; i++){
128       a[i] = b[i+x];
129    }
130 }
131
132 int G[M][N];
133 __attribute__((noinline))
134 void example8 (int x) {
135    int i,j;
136
137    /* feature: support for multidimensional arrays  */
138    for (i=0; i<M; i++) {
139      for (j=0; j<N; j++) {
140        G[i][j] = x;
141      }
142    }
143 }
144
145
146 __attribute__((noinline))
147 void example9 (unsigned *ret) {
148   int i;
149
150   /* feature: support summation reduction.
151      note: in case of floats use -funsafe-math-optimizations  */
152   unsigned int diff = 0;
153   for (i = 0; i < N; i++) {
154     diff += (ub[i] - uc[i]);
155   }
156
157   *ret = diff;
158 }
159
160
161 /* feature: support data-types of different sizes.
162    Currently only a single vector-size per target is supported; 
163    it can accommodate n elements such that n = vector-size/element-size 
164    (e.g, 4 ints, 8 shorts, or 16 chars for a vector of size 16 bytes). 
165    A combination of data-types of different sizes in the same loop 
166    requires special handling. This support is now present in mainline,
167    and also includes support for type conversions.  */
168 __attribute__((noinline))
169 void example10a(short *__restrict__ sa, short *__restrict__ sb, short *__restrict__ sc, int* __restrict__ ia, int* __restrict__ ib, int* __restrict__ ic) {
170   int i;
171   for (i = 0; i < N; i++) {
172     ia[i] = ib[i] + ic[i];
173     sa[i] = sb[i] + sc[i];
174   }
175 }
176
177 __attribute__((noinline))
178 void example10b(short *__restrict__ sa, short *__restrict__ sb, short *__restrict__ sc, int* __restrict__ ia, int* __restrict__ ib, int* __restrict__ ic) {
179   int i;
180   for (i = 0; i < N; i++) {
181     ia[i] = (int) sb[i];
182   }
183 }
184
185 /* feature: support strided accesses - the data elements
186    that are to be operated upon in parallel are not consecutive - they
187    are accessed with a stride > 1 (in the example, the stride is 2):  */
188 __attribute__((noinline))
189 void example11() {
190    int i;
191   for (i = 0; i < N/2; i++){
192     a[i] = b[2*i+1] * c[2*i+1] - b[2*i] * c[2*i];
193     d[i] = b[2*i] * c[2*i+1] + b[2*i+1] * c[2*i];
194   }
195 }
196
197
198 __attribute__((noinline))
199 void example12() {
200   for (int i = 0; i < N; i++) {
201     a[i] = i;
202   }
203 }
204
205 __attribute__((noinline))
206 void example13(int **A, int **B, int *out) {
207   int i,j;
208   for (i = 0; i < M; i++) {
209     int diff = 0;
210     for (j = 0; j < N; j+=8) {
211       diff += (A[i][j] - B[i][j]);
212     }
213     out[i] = diff;
214   }
215 }
216
217 __attribute__((noinline))
218 void example14(int **in, int **coeff, int *out) {
219   int k,j,i=0;
220   for (k = 0; k < K; k++) {
221     int sum = 0;
222     for (j = 0; j < M; j++)
223       for (i = 0; i < N; i++)
224           sum += in[i+k][j] * coeff[i][j];
225
226     out[k] = sum;
227   }
228
229 }
230
231
232 __attribute__((noinline))
233 void example21(int *b, int n) {
234   int i, a = 0;
235
236   for (i = n-1; i >= 0; i--)
237     a += b[i];
238
239   b[0] = a;
240 }
241
242 __attribute__((noinline))
243 void example23 (unsigned short *src, unsigned int *dst)
244 {
245   int i;
246
247   for (i = 0; i < 256; i++)
248     *dst++ = *src++ << 7;
249 }
250
251
252 __attribute__((noinline))
253 void example24 (short x, short y)
254 {
255   int i;
256   for (i = 0; i < N; i++)
257     ic[i] = fa[i] < fb[i] ? x : y;
258 }
259
260
261 __attribute__((noinline))
262 void example25 (void)
263 {
264   int i;
265   char x, y;
266   for (i = 0; i < N; i++)
267     {
268       x = (da[i] < db[i]);
269       y = (dc[i] < dd[i]);
270       dj[i] = x & y;
271     }
272 }
273
274 void init_memory(void *start, void* end) {
275   unsigned char state = 1;
276   while (start != end) {
277     state *= 7; state ^= 0x27; state += 1;
278     *((unsigned char*)start) = state;
279     start = ((char*)start) + 1;
280   }
281 }
282
283 void init_memory_float(float *start, float* end) {
284   float state = 1.0;
285   while (start != end) {
286     state *= 1.1;
287     *start = state;
288     start++;
289   }
290 }
291
292 unsigned digest_memory(void *start, void* end) {
293   unsigned state = 1;
294   while (start != end) {
295     state *= 3;
296     state ^= *((unsigned char*)start);
297     state = (state >> 8  ^ state << 8);
298     start = ((char*)start) + 1;
299   }
300   return state;
301 }
302
303 class Timer {
304
305 public:
306   Timer(const char* title, bool print) {
307     Title = title;
308     Print = print;
309     gettimeofday(&Start, 0);
310   }
311
312   ~Timer() {
313     gettimeofday(&End, 0);
314     long mtime, s,us;
315     s = End.tv_sec  - Start.tv_sec;
316     us = End.tv_usec - Start.tv_usec;
317     mtime = (s*1000 + us/1000.0)+0.5;
318     if (Print)
319       std::cout<<Title<<", "<<mtime<<", msec\n";
320   }
321
322 private:
323   const char* Title;
324   bool Print;
325   struct timeval Start, End;
326 };
327
328
329 // Warmup and then measure.
330 #define BENCH(NAME, RUN_LINE, ITER, DIGEST_LINE) {\
331   RUN_LINE;\
332   Timer atimer(NAME, print_times);\
333   for (int i=0; i < (ITER); ++i) RUN_LINE;\
334   unsigned r = DIGEST_LINE;\
335   results.push_back(r);\
336  }
337
338 int main(int argc,char* argv[]){
339
340   bool print_times = argc > 1;
341
342   std::vector<unsigned> results;
343   unsigned dummy = 0;
344 #ifdef SMALL_PROBLEM_SIZE
345   const int Mi = 1<<10;
346 #else
347   const int Mi = 1<<18;
348 #endif
349   init_memory(&ia[0], &ia[N]);
350   init_memory(&ib[0], &ib[N]);
351   init_memory(&ic[0], &ic[N]);
352   init_memory(&sa[0], &sa[N]);
353   init_memory(&sb[0], &sb[N]);
354   init_memory(&sc[0], &sc[N]);
355   init_memory(&a[0], &a[N*2]);
356   init_memory(&b[0], &b[N*2]);
357   init_memory(&c[0], &c[N*2]);
358   init_memory(&ua[0], &ua[N]);
359   init_memory(&ub[0], &ub[N]);
360   init_memory(&uc[0], &uc[N]);
361   init_memory(&G[0][0], &G[0][N]);
362   init_memory_float(&fa[0], &fa[N]);
363   init_memory_float(&fb[0], &fb[N]);
364   init_memory_float(&da[0], &da[N]);
365   init_memory_float(&db[0], &db[N]);
366   init_memory_float(&dc[0], &dc[N]);
367   init_memory_float(&dd[0], &dd[N]);
368
369   BENCH("Example1",   example1(), Mi*10, digest_memory(&a[0], &a[256]));
370   BENCH("Example2a",  example2a(N, 2), Mi*4, digest_memory(&b[0], &b[N]));
371   BENCH("Example2b",  example2b(N, 2), Mi*2, digest_memory(&a[0], &a[N]));
372   BENCH("Example3",   example3(N, ia, ib), Mi*2, digest_memory(&ia[0], &ia[N]));
373   BENCH("Example4a",  example4a(N, ia, ib), Mi*2, digest_memory(&ia[0], &ia[N]));
374   BENCH("Example4b",  example4b(N-10, ia, ib), Mi*2, digest_memory(&ia[0], &ia[N]));
375   BENCH("Example4c",  example4c(N, ia, ib), Mi*2, digest_memory(&ib[0], &ib[N]));
376   BENCH("Example7",   example7(4), Mi*4, digest_memory(&a[0], &a[N]));
377   BENCH("Example8",   example8(8), Mi/4, digest_memory(&G[0][0], &G[0][N]));
378   BENCH("Example9",   example9(&dummy), Mi*2, dummy);
379   BENCH("Example10a", example10a(sa,sb,sc,ia,ib,ic), Mi*2, digest_memory(&ia[0], &ia[N]) + digest_memory(&sa[0], &sa[N]));
380   BENCH("Example10b", example10b(sa,sb,sc,ia,ib,ic), Mi*4, digest_memory(&ia[0], &ia[N]));
381   BENCH("Example11",  example11(), Mi*2, digest_memory(&d[0], &d[N]));
382   BENCH("Example12",  example12(), Mi*4, digest_memory(&a[0], &a[N]));
383   //BENCH("Example21",  example21(ia, N), Mi*4, digest_memory(&ia[0], &ia[N]));
384   BENCH("Example23",  example23(usa,ua), Mi*8, digest_memory(&usa[0], &usa[256]));
385   BENCH("Example24",  example24(2,4), Mi*2, 0);
386   BENCH("Example25",  example25(), Mi*2, digest_memory(&dj[0], &dj[N]));
387
388   std::cout<<std::hex;
389   std::cout<<"Results: ("<<std::accumulate(results.begin(), results.end(), 0)<<"):";
390   for (unsigned i=0; i < results.size(); ++i) {
391     std::cout<<" "<<results[i];
392   }
393   std::cout<<"\n";
394
395   return 0;
396 }
397
398
399