summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/c11atomics.c
blob: fd5d3dea986a7ef724a4841bae615e48f1ca92e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-freebsd -std=c11 | FileCheck %s

// Test that we are generating atomicrmw instructions, rather than
// compare-exchange loops for common atomic ops.  This makes a big difference
// on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for
// the load and then another ll/sc in the loop, expanding to about 30
// instructions when it should be only 4.  It has a smaller, but still
// noticeable, impact on platforms like x86 and RISC-V, where there are atomic
// RMW instructions.
//
// We currently emit cmpxchg loops for most operations on _Bools, because
// they're sufficiently rare that it's not worth making sure that the semantics
// are correct.

typedef int __attribute__((vector_size(16))) vector;

_Atomic(_Bool) b;
_Atomic(int) i;
_Atomic(long long) l;
_Atomic(short) s;
_Atomic(char*) p;
_Atomic(float) f;
_Atomic(vector) v;

// CHECK-NOT: cmpxchg

// CHECK: testinc
void testinc(void)
{
  // Special case for suffix bool++, sets to true and returns the old value.
  // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst
  b++;
  // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
  i++;
  // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
  l++;
  // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
  s++;
  // Prefix increment
  // Special case for bool: set to true and return true
  // CHECK: store atomic i8 1, i8* @b seq_cst, align 1
  ++b;
  // Currently, we have no variant of atomicrmw that returns the new value, so
  // we have to generate an atomic add, which returns the old value, and then a
  // non-atomic add.
  // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
  // CHECK: add i32 
  ++i;
  // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
  // CHECK: add i64
  ++l;
  // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
  // CHECK: add i16
  ++s;
}
// CHECK: testdec
void testdec(void)
{
  // CHECK: cmpxchg i8* @b
  b--;
  // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
  i--;
  // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
  l--;
  // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
  s--;
  // CHECK: cmpxchg i8* @b
  --b;
  // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
  // CHECK: sub i32
  --i;
  // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
  // CHECK: sub i64
  --l;
  // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
  // CHECK: sub i16
  --s;
}
// CHECK: testaddeq
void testaddeq(void)
{
  // CHECK: cmpxchg i8* @b
  // CHECK: atomicrmw add i32* @i, i32 42 seq_cst
  // CHECK: atomicrmw add i64* @l, i64 42 seq_cst
  // CHECK: atomicrmw add i16* @s, i16 42 seq_cst
  b += 42;
  i += 42;
  l += 42;
  s += 42;
}
// CHECK: testsubeq
void testsubeq(void)
{
  // CHECK: cmpxchg i8* @b
  // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst
  // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst
  // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst
  b -= 42;
  i -= 42;
  l -= 42;
  s -= 42;
}
// CHECK: testxoreq
void testxoreq(void)
{
  // CHECK: cmpxchg i8* @b
  // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst
  // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst
  // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst
  b ^= 42;
  i ^= 42;
  l ^= 42;
  s ^= 42;
}
// CHECK: testoreq
void testoreq(void)
{
  // CHECK: cmpxchg i8* @b
  // CHECK: atomicrmw or i32* @i, i32 42 seq_cst
  // CHECK: atomicrmw or i64* @l, i64 42 seq_cst
  // CHECK: atomicrmw or i16* @s, i16 42 seq_cst
  b |= 42;
  i |= 42;
  l |= 42;
  s |= 42;
}
// CHECK: testandeq
void testandeq(void)
{
  // CHECK: cmpxchg i8* @b
  // CHECK: atomicrmw and i32* @i, i32 42 seq_cst
  // CHECK: atomicrmw and i64* @l, i64 42 seq_cst
  // CHECK: atomicrmw and i16* @s, i16 42 seq_cst
  b &= 42;
  i &= 42;
  l &= 42;
  s &= 42;
}

OpenPOWER on IntegriCloud