blob: 726fc5166fb0c8041eedf0b59664ff0c2b4a256e [file] [log] [blame]
David Chisnall72c1dba2013-03-03 16:02:42 +00001// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-freebsd -std=c11 | FileCheck %s
2
3// Test that we are generating atomicrmw instructions, rather than
4// compare-exchange loops for common atomic ops. This makes a big difference
5// on RISC platforms, where the compare-exchange loop becomes a ll/sc pair for
6// the load and then another ll/sc in the loop, expanding to about 30
7// instructions when it should be only 4. It has a smaller, but still
8// noticeable, impact on platforms like x86 and RISC-V, where there are atomic
9// RMW instructions.
10//
11// We currently emit cmpxchg loops for most operations on _Bools, because
12// they're sufficiently rare that it's not worth making sure that the semantics
13// are correct.
14
15typedef int __attribute__((vector_size(16))) vector;
16
17_Atomic(_Bool) b;
18_Atomic(int) i;
19_Atomic(long long) l;
20_Atomic(short) s;
21_Atomic(char*) p;
22_Atomic(float) f;
23_Atomic(vector) v;
24
David Chisnall72c1dba2013-03-03 16:02:42 +000025// CHECK: testinc
26void testinc(void)
27{
28 // Special case for suffix bool++, sets to true and returns the old value.
29 // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst
30 b++;
31 // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
32 i++;
33 // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
34 l++;
35 // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
36 s++;
37 // Prefix increment
38 // Special case for bool: set to true and return true
39 // CHECK: store atomic i8 1, i8* @b seq_cst, align 1
40 ++b;
41 // Currently, we have no variant of atomicrmw that returns the new value, so
42 // we have to generate an atomic add, which returns the old value, and then a
43 // non-atomic add.
44 // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
45 // CHECK: add i32
46 ++i;
47 // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
48 // CHECK: add i64
49 ++l;
50 // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
51 // CHECK: add i16
52 ++s;
53}
54// CHECK: testdec
55void testdec(void)
56{
57 // CHECK: cmpxchg i8* @b
58 b--;
59 // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
60 i--;
61 // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
62 l--;
63 // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
64 s--;
65 // CHECK: cmpxchg i8* @b
66 --b;
67 // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
68 // CHECK: sub i32
69 --i;
70 // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
71 // CHECK: sub i64
72 --l;
73 // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
74 // CHECK: sub i16
75 --s;
76}
77// CHECK: testaddeq
78void testaddeq(void)
79{
80 // CHECK: cmpxchg i8* @b
81 // CHECK: atomicrmw add i32* @i, i32 42 seq_cst
82 // CHECK: atomicrmw add i64* @l, i64 42 seq_cst
83 // CHECK: atomicrmw add i16* @s, i16 42 seq_cst
84 b += 42;
85 i += 42;
86 l += 42;
87 s += 42;
88}
89// CHECK: testsubeq
90void testsubeq(void)
91{
92 // CHECK: cmpxchg i8* @b
93 // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst
94 // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst
95 // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst
96 b -= 42;
97 i -= 42;
98 l -= 42;
99 s -= 42;
100}
101// CHECK: testxoreq
102void testxoreq(void)
103{
104 // CHECK: cmpxchg i8* @b
105 // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst
106 // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst
107 // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst
108 b ^= 42;
109 i ^= 42;
110 l ^= 42;
111 s ^= 42;
112}
113// CHECK: testoreq
114void testoreq(void)
115{
116 // CHECK: cmpxchg i8* @b
117 // CHECK: atomicrmw or i32* @i, i32 42 seq_cst
118 // CHECK: atomicrmw or i64* @l, i64 42 seq_cst
119 // CHECK: atomicrmw or i16* @s, i16 42 seq_cst
120 b |= 42;
121 i |= 42;
122 l |= 42;
123 s |= 42;
124}
125// CHECK: testandeq
126void testandeq(void)
127{
128 // CHECK: cmpxchg i8* @b
129 // CHECK: atomicrmw and i32* @i, i32 42 seq_cst
130 // CHECK: atomicrmw and i64* @l, i64 42 seq_cst
131 // CHECK: atomicrmw and i16* @s, i16 42 seq_cst
132 b &= 42;
133 i &= 42;
134 l &= 42;
135 s &= 42;
136}
137