1c4cb9b64SDmitry Vyukov // RUN: %clangxx_tsan %s -o %t
2c4cb9b64SDmitry Vyukov // RUN: %run %t 2>&1 | FileCheck %s
3c4cb9b64SDmitry Vyukov 
4c4cb9b64SDmitry Vyukov // bench.h needs pthread barriers which are not available on OS X
5c4cb9b64SDmitry Vyukov // UNSUPPORTED: darwin
6c4cb9b64SDmitry Vyukov 
7c4cb9b64SDmitry Vyukov #include "bench.h"
8c4cb9b64SDmitry Vyukov #include <memory.h>
9c4cb9b64SDmitry Vyukov 
thread(int tid)10c4cb9b64SDmitry Vyukov void thread(int tid) {
11c4cb9b64SDmitry Vyukov   volatile long x = 0;
12c4cb9b64SDmitry Vyukov   switch (bench_mode) {
13c4cb9b64SDmitry Vyukov   case 0:
14c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
15c4cb9b64SDmitry Vyukov       *(volatile char *)&x = 1;
16c4cb9b64SDmitry Vyukov     break;
17c4cb9b64SDmitry Vyukov   case 1:
18c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
19c4cb9b64SDmitry Vyukov       *(volatile short *)&x = 1;
20c4cb9b64SDmitry Vyukov     break;
21c4cb9b64SDmitry Vyukov   case 2:
22c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
23c4cb9b64SDmitry Vyukov       *(volatile int *)&x = 1;
24c4cb9b64SDmitry Vyukov     break;
25c4cb9b64SDmitry Vyukov   case 3:
26c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
27c4cb9b64SDmitry Vyukov       *(volatile long *)&x = 1;
28c4cb9b64SDmitry Vyukov     break;
29c4cb9b64SDmitry Vyukov   case 4:
30c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
31c4cb9b64SDmitry Vyukov       *(volatile char *)&x;
32c4cb9b64SDmitry Vyukov     break;
33c4cb9b64SDmitry Vyukov   case 5:
34c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
35c4cb9b64SDmitry Vyukov       *(volatile short *)&x;
36c4cb9b64SDmitry Vyukov     break;
37c4cb9b64SDmitry Vyukov   case 6:
38c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
39c4cb9b64SDmitry Vyukov       *(volatile int *)&x;
40c4cb9b64SDmitry Vyukov     break;
41c4cb9b64SDmitry Vyukov   case 7:
42c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
43c4cb9b64SDmitry Vyukov       *(volatile long *)&x;
44c4cb9b64SDmitry Vyukov   case 8:
45c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter / 10; i++) {
46c4cb9b64SDmitry Vyukov       ((volatile long *)&x)[0];
47c4cb9b64SDmitry Vyukov       ((volatile int *)&x)[0];
48c4cb9b64SDmitry Vyukov       ((volatile short *)&x)[2];
49c4cb9b64SDmitry Vyukov       ((volatile char *)&x)[6];
50c4cb9b64SDmitry Vyukov       ((volatile char *)&x)[7];
51c4cb9b64SDmitry Vyukov       ((volatile long *)&x)[0] = 1;
52c4cb9b64SDmitry Vyukov       ((volatile int *)&x)[0] = 1;
53c4cb9b64SDmitry Vyukov       ((volatile short *)&x)[2] = 1;
54c4cb9b64SDmitry Vyukov       ((volatile char *)&x)[6] = 1;
55c4cb9b64SDmitry Vyukov       ((volatile char *)&x)[7] = 1;
56c4cb9b64SDmitry Vyukov     }
57c4cb9b64SDmitry Vyukov     break;
58c4cb9b64SDmitry Vyukov   case 9: {
59c4cb9b64SDmitry Vyukov     volatile long size = sizeof(x);
60c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
61c4cb9b64SDmitry Vyukov       memset((void *)&x, i, size);
62c4cb9b64SDmitry Vyukov     break;
63c4cb9b64SDmitry Vyukov   }
64c4cb9b64SDmitry Vyukov   case 10: {
65c4cb9b64SDmitry Vyukov     volatile long data[2] = {};
66c4cb9b64SDmitry Vyukov     volatile long size = sizeof(data) - 2;
67c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter; i++)
68c4cb9b64SDmitry Vyukov       memset(((char *)data) + 1, i, size);
69c4cb9b64SDmitry Vyukov     break;
70c4cb9b64SDmitry Vyukov   }
71c4cb9b64SDmitry Vyukov   case 11: {
72c4cb9b64SDmitry Vyukov     volatile long data[2] = {};
73c4cb9b64SDmitry Vyukov     for (int i = 0; i < bench_niter / 8 / 3; i++) {
74c4cb9b64SDmitry Vyukov       for (int off = 0; off < 8; off++) {
75c4cb9b64SDmitry Vyukov         __sanitizer_unaligned_store16(((char *)data) + off, i);
76c4cb9b64SDmitry Vyukov         __sanitizer_unaligned_store32(((char *)data) + off, i);
77c4cb9b64SDmitry Vyukov         __sanitizer_unaligned_store64(((char *)data) + off, i);
78c4cb9b64SDmitry Vyukov       }
79c4cb9b64SDmitry Vyukov     }
80c4cb9b64SDmitry Vyukov     break;
81c4cb9b64SDmitry Vyukov   }
82*debac0efSDmitry Vyukov #if TSAN_VECTORIZE
83*debac0efSDmitry Vyukov   case 12: {
84*debac0efSDmitry Vyukov     // The compiler wants to optimize all this away.
85*debac0efSDmitry Vyukov     // Use volatile to prevent optimization, but then use kBlock
86*debac0efSDmitry Vyukov     // to avoid the additional non-vector load in the inner loop.
87*debac0efSDmitry Vyukov     // Also use only even indexes to prevent compiler from
88*debac0efSDmitry Vyukov     // inserting memset.
89*debac0efSDmitry Vyukov     const int kBlock = 128;
90*debac0efSDmitry Vyukov     __m128i data[kBlock * 2];
91*debac0efSDmitry Vyukov     __m128i *volatile vptr = data;
92*debac0efSDmitry Vyukov     for (int i = 0; i < bench_niter / kBlock; i++) {
93*debac0efSDmitry Vyukov       __m128i *ptr = vptr;
94*debac0efSDmitry Vyukov       for (int j = 0; j < kBlock; j++)
95*debac0efSDmitry Vyukov         _mm_store_si128(&ptr[j * 2], _mm_setzero_si128());
96*debac0efSDmitry Vyukov     }
97*debac0efSDmitry Vyukov     break;
98*debac0efSDmitry Vyukov   }
99*debac0efSDmitry Vyukov #endif
100c4cb9b64SDmitry Vyukov   }
101c4cb9b64SDmitry Vyukov }
102c4cb9b64SDmitry Vyukov 
bench()103c4cb9b64SDmitry Vyukov void bench() {
104c4cb9b64SDmitry Vyukov   start_thread_group(bench_nthread, thread);
105c4cb9b64SDmitry Vyukov }
106c4cb9b64SDmitry Vyukov 
107c4cb9b64SDmitry Vyukov // CHECK: DONE
108