1; RUN: llc < %s -O0 -march=x86-64 -mcpu=corei7 -verify-machineinstrs | FileCheck %s --check-prefix X64
2; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 -verify-machineinstrs | FileCheck %s --check-prefix X32
3; RUN: llc < %s -O0 -march=x86 -mcpu=corei7 -mattr=-cmov -verify-machineinstrs | FileCheck %s --check-prefix NOCMOV
4
5@sc32 = external global i32
6
7define void @atomic_fetch_add32() nounwind {
8; X64-LABEL:   atomic_fetch_add32:
9; X32-LABEL:   atomic_fetch_add32:
10entry:
11; 32-bit
12  %t1 = atomicrmw add  i32* @sc32, i32 1 acquire
13; X64:       lock
14; X64:       incl
15; X32:       lock
16; X32:       incl
17  %t2 = atomicrmw add  i32* @sc32, i32 3 acquire
18; X64:       lock
19; X64:       addl $3
20; X32:       lock
21; X32:       addl $3
22  %t3 = atomicrmw add  i32* @sc32, i32 5 acquire
23; X64:       lock
24; X64:       xaddl
25; X32:       lock
26; X32:       xaddl
27  %t4 = atomicrmw add  i32* @sc32, i32 %t3 acquire
28; X64:       lock
29; X64:       addl
30; X32:       lock
31; X32:       addl
32  ret void
33; X64:       ret
34; X32:       ret
35}
36
37define void @atomic_fetch_sub32() nounwind {
38; X64-LABEL:   atomic_fetch_sub32:
39; X32-LABEL:   atomic_fetch_sub32:
40  %t1 = atomicrmw sub  i32* @sc32, i32 1 acquire
41; X64:       lock
42; X64:       decl
43; X32:       lock
44; X32:       decl
45  %t2 = atomicrmw sub  i32* @sc32, i32 3 acquire
46; X64:       lock
47; X64:       subl $3
48; X32:       lock
49; X32:       subl $3
50  %t3 = atomicrmw sub  i32* @sc32, i32 5 acquire
51; X64:       lock
52; X64:       xaddl
53; X32:       lock
54; X32:       xaddl
55  %t4 = atomicrmw sub  i32* @sc32, i32 %t3 acquire
56; X64:       lock
57; X64:       subl
58; X32:       lock
59; X32:       subl
60  ret void
61; X64:       ret
62; X32:       ret
63}
64
65define void @atomic_fetch_and32() nounwind {
66; X64-LABEL:   atomic_fetch_and32:
67; X32-LABEL:   atomic_fetch_and32:
68  %t1 = atomicrmw and  i32* @sc32, i32 3 acquire
69; X64:       lock
70; X64:       andl $3
71; X32:       lock
72; X32:       andl $3
73  %t2 = atomicrmw and  i32* @sc32, i32 5 acquire
74; X64:       andl
75; X64:       lock
76; X64:       cmpxchgl
77; X32:       andl
78; X32:       lock
79; X32:       cmpxchgl
80  %t3 = atomicrmw and  i32* @sc32, i32 %t2 acquire
81; X64:       lock
82; X64:       andl
83; X32:       lock
84; X32:       andl
85  ret void
86; X64:       ret
87; X32:       ret
88}
89
90define void @atomic_fetch_or32() nounwind {
91; X64-LABEL:   atomic_fetch_or32:
92; X32-LABEL:   atomic_fetch_or32:
93  %t1 = atomicrmw or   i32* @sc32, i32 3 acquire
94; X64:       lock
95; X64:       orl $3
96; X32:       lock
97; X32:       orl $3
98  %t2 = atomicrmw or   i32* @sc32, i32 5 acquire
99; X64:       orl
100; X64:       lock
101; X64:       cmpxchgl
102; X32:       orl
103; X32:       lock
104; X32:       cmpxchgl
105  %t3 = atomicrmw or   i32* @sc32, i32 %t2 acquire
106; X64:       lock
107; X64:       orl
108; X32:       lock
109; X32:       orl
110  ret void
111; X64:       ret
112; X32:       ret
113}
114
115define void @atomic_fetch_xor32() nounwind {
116; X64-LABEL:   atomic_fetch_xor32:
117; X32-LABEL:   atomic_fetch_xor32:
118  %t1 = atomicrmw xor  i32* @sc32, i32 3 acquire
119; X64:       lock
120; X64:       xorl $3
121; X32:       lock
122; X32:       xorl $3
123  %t2 = atomicrmw xor  i32* @sc32, i32 5 acquire
124; X64:       xorl
125; X64:       lock
126; X64:       cmpxchgl
127; X32:       xorl
128; X32:       lock
129; X32:       cmpxchgl
130  %t3 = atomicrmw xor  i32* @sc32, i32 %t2 acquire
131; X64:       lock
132; X64:       xorl
133; X32:       lock
134; X32:       xorl
135  ret void
136; X64:       ret
137; X32:       ret
138}
139
140define void @atomic_fetch_nand32(i32 %x) nounwind {
141; X64-LABEL:   atomic_fetch_nand32:
142; X32-LABEL:   atomic_fetch_nand32:
143  %t1 = atomicrmw nand i32* @sc32, i32 %x acquire
144; X64:       andl
145; X64:       notl
146; X64:       lock
147; X64:       cmpxchgl
148; X32:       andl
149; X32:       notl
150; X32:       lock
151; X32:       cmpxchgl
152  ret void
153; X64:       ret
154; X32:       ret
155}
156
157define void @atomic_fetch_max32(i32 %x) nounwind {
158; X64-LABEL: atomic_fetch_max32:
159; X32-LABEL: atomic_fetch_max32:
160
161  %t1 = atomicrmw max  i32* @sc32, i32 %x acquire
162; X64:       subl
163; X64:       cmov
164; X64:       lock
165; X64:       cmpxchgl
166
167; X32:       subl
168; X32:       cmov
169; X32:       lock
170; X32:       cmpxchgl
171
172; NOCMOV:    subl
173; NOCMOV:    jge
174; NOCMOV:    lock
175; NOCMOV:    cmpxchgl
176  ret void
177; X64:       ret
178; X32:       ret
179; NOCMOV:    ret
180}
181
182define void @atomic_fetch_min32(i32 %x) nounwind {
183; X64-LABEL: atomic_fetch_min32:
184; X32-LABEL: atomic_fetch_min32:
185; NOCMOV-LABEL: atomic_fetch_min32:
186
187  %t1 = atomicrmw min  i32* @sc32, i32 %x acquire
188; X64:       subl
189; X64:       cmov
190; X64:       lock
191; X64:       cmpxchgl
192
193; X32:       subl
194; X32:       cmov
195; X32:       lock
196; X32:       cmpxchgl
197
198; NOCMOV:    subl
199; NOCMOV:    jle
200; NOCMOV:    lock
201; NOCMOV:    cmpxchgl
202  ret void
203; X64:       ret
204; X32:       ret
205; NOCMOV:    ret
206}
207
208define void @atomic_fetch_umax32(i32 %x) nounwind {
209; X64-LABEL: atomic_fetch_umax32:
210; X32-LABEL: atomic_fetch_umax32:
211; NOCMOV-LABEL: atomic_fetch_umax32:
212
213  %t1 = atomicrmw umax i32* @sc32, i32 %x acquire
214; X64:       subl
215; X64:       cmov
216; X64:       lock
217; X64:       cmpxchgl
218
219; X32:       subl
220; X32:       cmov
221; X32:       lock
222; X32:       cmpxchgl
223
224; NOCMOV:    subl
225; NOCMOV:    ja
226; NOCMOV:    lock
227; NOCMOV:    cmpxchgl
228  ret void
229; X64:       ret
230; X32:       ret
231; NOCMOV:    ret
232}
233
234define void @atomic_fetch_umin32(i32 %x) nounwind {
235; X64-LABEL: atomic_fetch_umin32:
236; X32-LABEL: atomic_fetch_umin32:
237; NOCMOV-LABEL: atomic_fetch_umin32:
238
239  %t1 = atomicrmw umin i32* @sc32, i32 %x acquire
240; X64:       subl
241; X64:       cmov
242; X64:       lock
243; X64:       cmpxchgl
244
245; X32:       subl
246; X32:       cmov
247; X32:       lock
248; X32:       cmpxchgl
249
250; NOCMOV:    subl
251; NOCMOV:    jb
252; NOCMOV:    lock
253; NOCMOV:    cmpxchgl
254  ret void
255; X64:       ret
256; X32:       ret
257; NOCMOV:    ret
258}
259
260define void @atomic_fetch_cmpxchg32() nounwind {
261; X64-LABEL: atomic_fetch_cmpxchg32:
262; X32-LABEL: atomic_fetch_cmpxchg32:
263
264  %t1 = cmpxchg i32* @sc32, i32 0, i32 1 acquire acquire
265; X64:       lock
266; X64:       cmpxchgl
267; X32:       lock
268; X32:       cmpxchgl
269  ret void
270; X64:       ret
271; X32:       ret
272}
273
274define void @atomic_fetch_store32(i32 %x) nounwind {
275; X64-LABEL: atomic_fetch_store32:
276; X32-LABEL: atomic_fetch_store32:
277
278  store atomic i32 %x, i32* @sc32 release, align 4
279; X64-NOT:   lock
280; X64:       movl
281; X32-NOT:   lock
282; X32:       movl
283  ret void
284; X64:       ret
285; X32:       ret
286}
287
288define void @atomic_fetch_swap32(i32 %x) nounwind {
289; X64-LABEL: atomic_fetch_swap32:
290; X32-LABEL: atomic_fetch_swap32:
291
292  %t1 = atomicrmw xchg i32* @sc32, i32 %x acquire
293; X64-NOT:   lock
294; X64:       xchgl
295; X32-NOT:   lock
296; X32:       xchgl
297  ret void
298; X64:       ret
299; X32:       ret
300}
301