blob: fd5d3dea986a7ef724a4841bae615e48f1ca92e3 [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
25// CHECK-NOT: cmpxchg
26
27// CHECK: testinc
28void testinc(void)
29{
30 // Special case for suffix bool++, sets to true and returns the old value.
31 // CHECK: atomicrmw xchg i8* @b, i8 1 seq_cst
32 b++;
33 // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
34 i++;
35 // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
36 l++;
37 // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
38 s++;
39 // Prefix increment
40 // Special case for bool: set to true and return true
41 // CHECK: store atomic i8 1, i8* @b seq_cst, align 1
42 ++b;
43 // Currently, we have no variant of atomicrmw that returns the new value, so
44 // we have to generate an atomic add, which returns the old value, and then a
45 // non-atomic add.
46 // CHECK: atomicrmw add i32* @i, i32 1 seq_cst
47 // CHECK: add i32
48 ++i;
49 // CHECK: atomicrmw add i64* @l, i64 1 seq_cst
50 // CHECK: add i64
51 ++l;
52 // CHECK: atomicrmw add i16* @s, i16 1 seq_cst
53 // CHECK: add i16
54 ++s;
55}
56// CHECK: testdec
57void testdec(void)
58{
59 // CHECK: cmpxchg i8* @b
60 b--;
61 // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
62 i--;
63 // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
64 l--;
65 // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
66 s--;
67 // CHECK: cmpxchg i8* @b
68 --b;
69 // CHECK: atomicrmw sub i32* @i, i32 1 seq_cst
70 // CHECK: sub i32
71 --i;
72 // CHECK: atomicrmw sub i64* @l, i64 1 seq_cst
73 // CHECK: sub i64
74 --l;
75 // CHECK: atomicrmw sub i16* @s, i16 1 seq_cst
76 // CHECK: sub i16
77 --s;
78}
79// CHECK: testaddeq
80void testaddeq(void)
81{
82 // CHECK: cmpxchg i8* @b
83 // CHECK: atomicrmw add i32* @i, i32 42 seq_cst
84 // CHECK: atomicrmw add i64* @l, i64 42 seq_cst
85 // CHECK: atomicrmw add i16* @s, i16 42 seq_cst
86 b += 42;
87 i += 42;
88 l += 42;
89 s += 42;
90}
91// CHECK: testsubeq
92void testsubeq(void)
93{
94 // CHECK: cmpxchg i8* @b
95 // CHECK: atomicrmw sub i32* @i, i32 42 seq_cst
96 // CHECK: atomicrmw sub i64* @l, i64 42 seq_cst
97 // CHECK: atomicrmw sub i16* @s, i16 42 seq_cst
98 b -= 42;
99 i -= 42;
100 l -= 42;
101 s -= 42;
102}
103// CHECK: testxoreq
104void testxoreq(void)
105{
106 // CHECK: cmpxchg i8* @b
107 // CHECK: atomicrmw xor i32* @i, i32 42 seq_cst
108 // CHECK: atomicrmw xor i64* @l, i64 42 seq_cst
109 // CHECK: atomicrmw xor i16* @s, i16 42 seq_cst
110 b ^= 42;
111 i ^= 42;
112 l ^= 42;
113 s ^= 42;
114}
115// CHECK: testoreq
116void testoreq(void)
117{
118 // CHECK: cmpxchg i8* @b
119 // CHECK: atomicrmw or i32* @i, i32 42 seq_cst
120 // CHECK: atomicrmw or i64* @l, i64 42 seq_cst
121 // CHECK: atomicrmw or i16* @s, i16 42 seq_cst
122 b |= 42;
123 i |= 42;
124 l |= 42;
125 s |= 42;
126}
127// CHECK: testandeq
128void testandeq(void)
129{
130 // CHECK: cmpxchg i8* @b
131 // CHECK: atomicrmw and i32* @i, i32 42 seq_cst
132 // CHECK: atomicrmw and i64* @l, i64 42 seq_cst
133 // CHECK: atomicrmw and i16* @s, i16 42 seq_cst
134 b &= 42;
135 i &= 42;
136 l &= 42;
137 s &= 42;
138}
139