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