xref: /llvm-project/compiler-rt/test/tsan/vector_race.cpp (revision 5cac2b956bcf42495a2253443502fb73dbb43c3d)
1*5cac2b95SDmitry Vyukov // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t 2>&1 | FileCheck %s
2*5cac2b95SDmitry Vyukov #include "test.h"
3*5cac2b95SDmitry Vyukov 
4*5cac2b95SDmitry Vyukov __m128i data[20];
5*5cac2b95SDmitry Vyukov 
load(__m128i * v)6*5cac2b95SDmitry Vyukov __m128i load(__m128i *v) {
7*5cac2b95SDmitry Vyukov #if TSAN_VECTORIZE
8*5cac2b95SDmitry Vyukov   return _mm_load_si128(v);
9*5cac2b95SDmitry Vyukov #else
10*5cac2b95SDmitry Vyukov   return *v;
11*5cac2b95SDmitry Vyukov #endif
12*5cac2b95SDmitry Vyukov }
13*5cac2b95SDmitry Vyukov 
store(__m128i * v,__m128i a)14*5cac2b95SDmitry Vyukov void store(__m128i *v, __m128i a) {
15*5cac2b95SDmitry Vyukov #if TSAN_VECTORIZE
16*5cac2b95SDmitry Vyukov   _mm_store_si128(v, a);
17*5cac2b95SDmitry Vyukov #else
18*5cac2b95SDmitry Vyukov   *v = a;
19*5cac2b95SDmitry Vyukov #endif
20*5cac2b95SDmitry Vyukov }
21*5cac2b95SDmitry Vyukov 
22*5cac2b95SDmitry Vyukov void *Thread(void *arg);
23*5cac2b95SDmitry Vyukov 
main()24*5cac2b95SDmitry Vyukov int main() {
25*5cac2b95SDmitry Vyukov   barrier_init(&barrier, 2);
26*5cac2b95SDmitry Vyukov   pthread_t th;
27*5cac2b95SDmitry Vyukov   pthread_create(&th, NULL, Thread, NULL);
28*5cac2b95SDmitry Vyukov   barrier_wait(&barrier);
29*5cac2b95SDmitry Vyukov 
30*5cac2b95SDmitry Vyukov   print_address("addr0:", 2, &data[0], &data[0]);
31*5cac2b95SDmitry Vyukov   auto v0 = load(&data[1]);
32*5cac2b95SDmitry Vyukov   store(&data[0], v0);
33*5cac2b95SDmitry Vyukov   // CHECK: addr0:[[ADDR0_0:0x[0-9,a-f]+]] [[ADDR0_1:0x[0-9,a-f]+]]
34*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
35*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 8 at [[ADDR0_0]] by main thread:
36*5cac2b95SDmitry Vyukov   // CHECK:   Previous read of size 8 at [[ADDR0_1]] by thread T1:
37*5cac2b95SDmitry Vyukov 
38*5cac2b95SDmitry Vyukov   print_address("addr1:", 2, (char *)&data[2] + 8, (char *)&data[2] + 8);
39*5cac2b95SDmitry Vyukov   ((volatile unsigned long long *)(&data[2]))[1] = 42;
40*5cac2b95SDmitry Vyukov   // CHECK: addr1:[[ADDR1_0:0x[0-9,a-f]+]] [[ADDR1_1:0x[0-9,a-f]+]]
41*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
42*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 8 at [[ADDR1_0]] by main thread:
43*5cac2b95SDmitry Vyukov   // CHECK:   Previous read of size 8 at [[ADDR1_1]] by thread T1:
44*5cac2b95SDmitry Vyukov 
45*5cac2b95SDmitry Vyukov   print_address("addr2:", 2, (char *)&data[4] + 15, (char *)&data[4] + 8);
46*5cac2b95SDmitry Vyukov   ((volatile char *)(&data[4]))[15] = 42;
47*5cac2b95SDmitry Vyukov   // CHECK: addr2:[[ADDR2_0:0x[0-9,a-f]+]] [[ADDR2_1:0x[0-9,a-f]+]]
48*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
49*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 1 at [[ADDR2_0]] by main thread:
50*5cac2b95SDmitry Vyukov   // CHECK:   Previous read of size 8 at [[ADDR2_1]] by thread T1:
51*5cac2b95SDmitry Vyukov 
52*5cac2b95SDmitry Vyukov   store(&data[12], v0);
53*5cac2b95SDmitry Vyukov   ((volatile unsigned long long *)(&data[14]))[1] = 42;
54*5cac2b95SDmitry Vyukov   ((volatile char *)(&data[16]))[15] = 42;
55*5cac2b95SDmitry Vyukov   barrier_wait(&barrier);
56*5cac2b95SDmitry Vyukov   pthread_join(th, NULL);
57*5cac2b95SDmitry Vyukov   return 0;
58*5cac2b95SDmitry Vyukov }
59*5cac2b95SDmitry Vyukov 
Thread(void * arg)60*5cac2b95SDmitry Vyukov void *Thread(void *arg) {
61*5cac2b95SDmitry Vyukov   // Use only even indexes so that compiler does not insert memcpy.
62*5cac2b95SDmitry Vyukov   auto v0 = load(&data[0]);
63*5cac2b95SDmitry Vyukov   auto v1 = load(&data[2]);
64*5cac2b95SDmitry Vyukov   auto v2 = load(&data[4]);
65*5cac2b95SDmitry Vyukov   store(&data[6], v0);
66*5cac2b95SDmitry Vyukov   store(&data[8], v1);
67*5cac2b95SDmitry Vyukov   store(&data[10], v2);
68*5cac2b95SDmitry Vyukov   barrier_wait(&barrier);
69*5cac2b95SDmitry Vyukov   barrier_wait(&barrier);
70*5cac2b95SDmitry Vyukov 
71*5cac2b95SDmitry Vyukov   print_address("addr3:", 2, &data[12], &data[12]);
72*5cac2b95SDmitry Vyukov   store(&data[12], v0);
73*5cac2b95SDmitry Vyukov   // CHECK: addr3:[[ADDR3_0:0x[0-9,a-f]+]] [[ADDR3_1:0x[0-9,a-f]+]]
74*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
75*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 8 at [[ADDR3_0]] by thread T1:
76*5cac2b95SDmitry Vyukov   // CHECK:   Previous write of size 8 at [[ADDR3_1]] by main thread:
77*5cac2b95SDmitry Vyukov 
78*5cac2b95SDmitry Vyukov   print_address("addr4:", 2, (char *)&data[14] + 8, (char *)&data[14] + 8);
79*5cac2b95SDmitry Vyukov   store(&data[14], v0);
80*5cac2b95SDmitry Vyukov   // CHECK: addr4:[[ADDR4_0:0x[0-9,a-f]+]] [[ADDR4_1:0x[0-9,a-f]+]]
81*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
82*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 8 at [[ADDR4_0]] by thread T1:
83*5cac2b95SDmitry Vyukov   // CHECK:   Previous write of size 8 at [[ADDR4_1]] by main thread:
84*5cac2b95SDmitry Vyukov 
85*5cac2b95SDmitry Vyukov   print_address("addr5:", 2, (char *)&data[16] + 8, (char *)&data[16] + 15);
86*5cac2b95SDmitry Vyukov   store(&data[16], v0);
87*5cac2b95SDmitry Vyukov   // CHECK: addr5:[[ADDR5_0:0x[0-9,a-f]+]] [[ADDR5_1:0x[0-9,a-f]+]]
88*5cac2b95SDmitry Vyukov   // CHECK: WARNING: ThreadSanitizer: data race
89*5cac2b95SDmitry Vyukov   // CHECK:   Write of size 8 at [[ADDR5_0]] by thread T1:
90*5cac2b95SDmitry Vyukov   // CHECK:   Previous write of size 1 at [[ADDR5_1]] by main thread:
91*5cac2b95SDmitry Vyukov   return NULL;
92*5cac2b95SDmitry Vyukov }
93