1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-- -verify-machineinstrs                           | FileCheck %s --check-prefix=X64
3; RUN: llc < %s -mtriple=i686-- -verify-machineinstrs           -mattr=+sse2      | FileCheck %s --check-prefixes=X86,X86-GENERIC,X86-SSE2
4; RUN: llc < %s -mtriple=i686-- -verify-machineinstrs -mcpu=slm -mattr=-sse2      | FileCheck %s --check-prefixes=X86,X86-GENERIC,X86-SLM
5; RUN: llc < %s -mtriple=i686-- -verify-machineinstrs -mcpu=goldmont -mattr=-sse2 | FileCheck %s --check-prefixes=X86,X86-GENERIC,X86-SLM
6; RUN: llc < %s -mtriple=i686-- -verify-machineinstrs -mcpu=knl -mattr=-sse2      | FileCheck %s --check-prefixes=X86,X86-GENERIC,X86-SLM
7; RUN: llc < %s -mtriple=i686-- -verify-machineinstrs -mcpu=atom -mattr=-sse2     | FileCheck %s --check-prefixes=X86,X86-ATOM
8
9; On x86, an atomic rmw operation that does not modify the value in memory
10; (such as atomic add 0) can be replaced by an mfence followed by a mov.
11; This is explained (with the motivation for such an optimization) in
12; http://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
13
14define i8 @add8(ptr %p) {
15; X64-LABEL: add8:
16; X64:       # %bb.0:
17; X64-NEXT:    mfence
18; X64-NEXT:    movzbl (%rdi), %eax
19; X64-NEXT:    retq
20;
21; X86-SSE2-LABEL: add8:
22; X86-SSE2:       # %bb.0:
23; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
24; X86-SSE2-NEXT:    mfence
25; X86-SSE2-NEXT:    movzbl (%eax), %eax
26; X86-SSE2-NEXT:    retl
27;
28; X86-SLM-LABEL: add8:
29; X86-SLM:       # %bb.0:
30; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
31; X86-SLM-NEXT:    xorl %eax, %eax
32; X86-SLM-NEXT:    lock xaddb %al, (%ecx)
33; X86-SLM-NEXT:    # kill: def $al killed $al killed $eax
34; X86-SLM-NEXT:    retl
35;
36; X86-ATOM-LABEL: add8:
37; X86-ATOM:       # %bb.0:
38; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
39; X86-ATOM-NEXT:    xorl %eax, %eax
40; X86-ATOM-NEXT:    lock xaddb %al, (%ecx)
41; X86-ATOM-NEXT:    # kill: def $al killed $al killed $eax
42; X86-ATOM-NEXT:    nop
43; X86-ATOM-NEXT:    nop
44; X86-ATOM-NEXT:    retl
45  %1 = atomicrmw add ptr %p, i8 0 monotonic
46  ret i8 %1
47}
48
49define i16 @or16(ptr %p) {
50; X64-LABEL: or16:
51; X64:       # %bb.0:
52; X64-NEXT:    mfence
53; X64-NEXT:    movzwl (%rdi), %eax
54; X64-NEXT:    retq
55;
56; X86-SSE2-LABEL: or16:
57; X86-SSE2:       # %bb.0:
58; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
59; X86-SSE2-NEXT:    mfence
60; X86-SSE2-NEXT:    movzwl (%eax), %eax
61; X86-SSE2-NEXT:    retl
62;
63; X86-SLM-LABEL: or16:
64; X86-SLM:       # %bb.0:
65; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
66; X86-SLM-NEXT:    movzwl (%ecx), %eax
67; X86-SLM-NEXT:    .p2align 4, 0x90
68; X86-SLM-NEXT:  .LBB1_1: # %atomicrmw.start
69; X86-SLM-NEXT:    # =>This Inner Loop Header: Depth=1
70; X86-SLM-NEXT:    lock cmpxchgw %ax, (%ecx)
71; X86-SLM-NEXT:    jne .LBB1_1
72; X86-SLM-NEXT:  # %bb.2: # %atomicrmw.end
73; X86-SLM-NEXT:    retl
74;
75; X86-ATOM-LABEL: or16:
76; X86-ATOM:       # %bb.0:
77; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
78; X86-ATOM-NEXT:    movzwl (%ecx), %eax
79; X86-ATOM-NEXT:    .p2align 4, 0x90
80; X86-ATOM-NEXT:  .LBB1_1: # %atomicrmw.start
81; X86-ATOM-NEXT:    # =>This Inner Loop Header: Depth=1
82; X86-ATOM-NEXT:    lock cmpxchgw %ax, (%ecx)
83; X86-ATOM-NEXT:    jne .LBB1_1
84; X86-ATOM-NEXT:  # %bb.2: # %atomicrmw.end
85; X86-ATOM-NEXT:    retl
86  %1 = atomicrmw or ptr %p, i16 0 acquire
87  ret i16 %1
88}
89
90define i32 @xor32(ptr %p) {
91; X64-LABEL: xor32:
92; X64:       # %bb.0:
93; X64-NEXT:    mfence
94; X64-NEXT:    movl (%rdi), %eax
95; X64-NEXT:    retq
96;
97; X86-SSE2-LABEL: xor32:
98; X86-SSE2:       # %bb.0:
99; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
100; X86-SSE2-NEXT:    mfence
101; X86-SSE2-NEXT:    movl (%eax), %eax
102; X86-SSE2-NEXT:    retl
103;
104; X86-SLM-LABEL: xor32:
105; X86-SLM:       # %bb.0:
106; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
107; X86-SLM-NEXT:    movl (%ecx), %eax
108; X86-SLM-NEXT:    .p2align 4, 0x90
109; X86-SLM-NEXT:  .LBB2_1: # %atomicrmw.start
110; X86-SLM-NEXT:    # =>This Inner Loop Header: Depth=1
111; X86-SLM-NEXT:    lock cmpxchgl %eax, (%ecx)
112; X86-SLM-NEXT:    jne .LBB2_1
113; X86-SLM-NEXT:  # %bb.2: # %atomicrmw.end
114; X86-SLM-NEXT:    retl
115;
116; X86-ATOM-LABEL: xor32:
117; X86-ATOM:       # %bb.0:
118; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
119; X86-ATOM-NEXT:    movl (%ecx), %eax
120; X86-ATOM-NEXT:    .p2align 4, 0x90
121; X86-ATOM-NEXT:  .LBB2_1: # %atomicrmw.start
122; X86-ATOM-NEXT:    # =>This Inner Loop Header: Depth=1
123; X86-ATOM-NEXT:    lock cmpxchgl %eax, (%ecx)
124; X86-ATOM-NEXT:    jne .LBB2_1
125; X86-ATOM-NEXT:  # %bb.2: # %atomicrmw.end
126; X86-ATOM-NEXT:    retl
127  %1 = atomicrmw xor ptr %p, i32 0 release
128  ret i32 %1
129}
130
131define i64 @sub64(ptr %p) {
132; X64-LABEL: sub64:
133; X64:       # %bb.0:
134; X64-NEXT:    mfence
135; X64-NEXT:    movq (%rdi), %rax
136; X64-NEXT:    retq
137;
138; X86-LABEL: sub64:
139; X86:       # %bb.0:
140; X86-NEXT:    pushl %ebx
141; X86-NEXT:    .cfi_def_cfa_offset 8
142; X86-NEXT:    pushl %esi
143; X86-NEXT:    .cfi_def_cfa_offset 12
144; X86-NEXT:    .cfi_offset %esi, -12
145; X86-NEXT:    .cfi_offset %ebx, -8
146; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
147; X86-NEXT:    movl (%esi), %eax
148; X86-NEXT:    movl 4(%esi), %edx
149; X86-NEXT:    .p2align 4, 0x90
150; X86-NEXT:  .LBB3_1: # %atomicrmw.start
151; X86-NEXT:    # =>This Inner Loop Header: Depth=1
152; X86-NEXT:    movl %edx, %ecx
153; X86-NEXT:    movl %eax, %ebx
154; X86-NEXT:    lock cmpxchg8b (%esi)
155; X86-NEXT:    jne .LBB3_1
156; X86-NEXT:  # %bb.2: # %atomicrmw.end
157; X86-NEXT:    popl %esi
158; X86-NEXT:    .cfi_def_cfa_offset 8
159; X86-NEXT:    popl %ebx
160; X86-NEXT:    .cfi_def_cfa_offset 4
161; X86-NEXT:    retl
162  %1 = atomicrmw sub ptr %p, i64 0 seq_cst
163  ret i64 %1
164}
165
166define i128 @or128(ptr %p) {
167; X64-LABEL: or128:
168; X64:       # %bb.0:
169; X64-NEXT:    pushq %rax
170; X64-NEXT:    .cfi_def_cfa_offset 16
171; X64-NEXT:    xorl %esi, %esi
172; X64-NEXT:    xorl %edx, %edx
173; X64-NEXT:    callq __sync_fetch_and_or_16@PLT
174; X64-NEXT:    popq %rcx
175; X64-NEXT:    .cfi_def_cfa_offset 8
176; X64-NEXT:    retq
177;
178; X86-SSE2-LABEL: or128:
179; X86-SSE2:       # %bb.0:
180; X86-SSE2-NEXT:    pushl %ebp
181; X86-SSE2-NEXT:    .cfi_def_cfa_offset 8
182; X86-SSE2-NEXT:    .cfi_offset %ebp, -8
183; X86-SSE2-NEXT:    movl %esp, %ebp
184; X86-SSE2-NEXT:    .cfi_def_cfa_register %ebp
185; X86-SSE2-NEXT:    pushl %edi
186; X86-SSE2-NEXT:    pushl %esi
187; X86-SSE2-NEXT:    andl $-8, %esp
188; X86-SSE2-NEXT:    subl $16, %esp
189; X86-SSE2-NEXT:    .cfi_offset %esi, -16
190; X86-SSE2-NEXT:    .cfi_offset %edi, -12
191; X86-SSE2-NEXT:    movl 8(%ebp), %esi
192; X86-SSE2-NEXT:    movl %esp, %eax
193; X86-SSE2-NEXT:    pushl $0
194; X86-SSE2-NEXT:    pushl $0
195; X86-SSE2-NEXT:    pushl $0
196; X86-SSE2-NEXT:    pushl $0
197; X86-SSE2-NEXT:    pushl 12(%ebp)
198; X86-SSE2-NEXT:    pushl %eax
199; X86-SSE2-NEXT:    calll __sync_fetch_and_or_16
200; X86-SSE2-NEXT:    addl $20, %esp
201; X86-SSE2-NEXT:    movl (%esp), %eax
202; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %ecx
203; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %edx
204; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %edi
205; X86-SSE2-NEXT:    movl %edi, 8(%esi)
206; X86-SSE2-NEXT:    movl %edx, 12(%esi)
207; X86-SSE2-NEXT:    movl %eax, (%esi)
208; X86-SSE2-NEXT:    movl %ecx, 4(%esi)
209; X86-SSE2-NEXT:    movl %esi, %eax
210; X86-SSE2-NEXT:    leal -8(%ebp), %esp
211; X86-SSE2-NEXT:    popl %esi
212; X86-SSE2-NEXT:    popl %edi
213; X86-SSE2-NEXT:    popl %ebp
214; X86-SSE2-NEXT:    .cfi_def_cfa %esp, 4
215; X86-SSE2-NEXT:    retl $4
216;
217; X86-SLM-LABEL: or128:
218; X86-SLM:       # %bb.0:
219; X86-SLM-NEXT:    pushl %ebp
220; X86-SLM-NEXT:    .cfi_def_cfa_offset 8
221; X86-SLM-NEXT:    .cfi_offset %ebp, -8
222; X86-SLM-NEXT:    movl %esp, %ebp
223; X86-SLM-NEXT:    .cfi_def_cfa_register %ebp
224; X86-SLM-NEXT:    pushl %edi
225; X86-SLM-NEXT:    pushl %esi
226; X86-SLM-NEXT:    andl $-8, %esp
227; X86-SLM-NEXT:    subl $16, %esp
228; X86-SLM-NEXT:    .cfi_offset %esi, -16
229; X86-SLM-NEXT:    .cfi_offset %edi, -12
230; X86-SLM-NEXT:    movl 8(%ebp), %esi
231; X86-SLM-NEXT:    movl 12(%ebp), %eax
232; X86-SLM-NEXT:    movl %esp, %ecx
233; X86-SLM-NEXT:    pushl $0
234; X86-SLM-NEXT:    pushl $0
235; X86-SLM-NEXT:    pushl $0
236; X86-SLM-NEXT:    pushl $0
237; X86-SLM-NEXT:    pushl %eax
238; X86-SLM-NEXT:    pushl %ecx
239; X86-SLM-NEXT:    calll __sync_fetch_and_or_16
240; X86-SLM-NEXT:    addl $20, %esp
241; X86-SLM-NEXT:    movl (%esp), %eax
242; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
243; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %edx
244; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %edi
245; X86-SLM-NEXT:    movl %edi, 8(%esi)
246; X86-SLM-NEXT:    movl %edx, 12(%esi)
247; X86-SLM-NEXT:    movl %eax, (%esi)
248; X86-SLM-NEXT:    movl %ecx, 4(%esi)
249; X86-SLM-NEXT:    movl %esi, %eax
250; X86-SLM-NEXT:    leal -8(%ebp), %esp
251; X86-SLM-NEXT:    popl %esi
252; X86-SLM-NEXT:    popl %edi
253; X86-SLM-NEXT:    popl %ebp
254; X86-SLM-NEXT:    .cfi_def_cfa %esp, 4
255; X86-SLM-NEXT:    retl $4
256;
257; X86-ATOM-LABEL: or128:
258; X86-ATOM:       # %bb.0:
259; X86-ATOM-NEXT:    pushl %ebp
260; X86-ATOM-NEXT:    .cfi_def_cfa_offset 8
261; X86-ATOM-NEXT:    .cfi_offset %ebp, -8
262; X86-ATOM-NEXT:    leal (%esp), %ebp
263; X86-ATOM-NEXT:    .cfi_def_cfa_register %ebp
264; X86-ATOM-NEXT:    pushl %edi
265; X86-ATOM-NEXT:    pushl %esi
266; X86-ATOM-NEXT:    andl $-8, %esp
267; X86-ATOM-NEXT:    leal -{{[0-9]+}}(%esp), %esp
268; X86-ATOM-NEXT:    .cfi_offset %esi, -16
269; X86-ATOM-NEXT:    .cfi_offset %edi, -12
270; X86-ATOM-NEXT:    movl 8(%ebp), %esi
271; X86-ATOM-NEXT:    movl 12(%ebp), %eax
272; X86-ATOM-NEXT:    movl %esp, %ecx
273; X86-ATOM-NEXT:    pushl $0
274; X86-ATOM-NEXT:    pushl $0
275; X86-ATOM-NEXT:    pushl $0
276; X86-ATOM-NEXT:    pushl $0
277; X86-ATOM-NEXT:    pushl %eax
278; X86-ATOM-NEXT:    pushl %ecx
279; X86-ATOM-NEXT:    calll __sync_fetch_and_or_16
280; X86-ATOM-NEXT:    leal {{[0-9]+}}(%esp), %esp
281; X86-ATOM-NEXT:    movl (%esp), %ecx
282; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %edx
283; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %eax
284; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %edi
285; X86-ATOM-NEXT:    movl %eax, 8(%esi)
286; X86-ATOM-NEXT:    movl %edi, 12(%esi)
287; X86-ATOM-NEXT:    movl %ecx, (%esi)
288; X86-ATOM-NEXT:    movl %esi, %eax
289; X86-ATOM-NEXT:    movl %edx, 4(%esi)
290; X86-ATOM-NEXT:    leal -8(%ebp), %esp
291; X86-ATOM-NEXT:    popl %esi
292; X86-ATOM-NEXT:    popl %edi
293; X86-ATOM-NEXT:    popl %ebp
294; X86-ATOM-NEXT:    .cfi_def_cfa %esp, 4
295; X86-ATOM-NEXT:    retl $4
296  %1 = atomicrmw or ptr %p, i128 0 monotonic
297  ret i128 %1
298}
299
300; For 'and', the idempotent value is (-1)
301define i32 @and32 (ptr %p) {
302; X64-LABEL: and32:
303; X64:       # %bb.0:
304; X64-NEXT:    mfence
305; X64-NEXT:    movl (%rdi), %eax
306; X64-NEXT:    retq
307;
308; X86-SSE2-LABEL: and32:
309; X86-SSE2:       # %bb.0:
310; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
311; X86-SSE2-NEXT:    mfence
312; X86-SSE2-NEXT:    movl (%eax), %eax
313; X86-SSE2-NEXT:    retl
314;
315; X86-SLM-LABEL: and32:
316; X86-SLM:       # %bb.0:
317; X86-SLM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
318; X86-SLM-NEXT:    movl (%ecx), %eax
319; X86-SLM-NEXT:    .p2align 4, 0x90
320; X86-SLM-NEXT:  .LBB5_1: # %atomicrmw.start
321; X86-SLM-NEXT:    # =>This Inner Loop Header: Depth=1
322; X86-SLM-NEXT:    lock cmpxchgl %eax, (%ecx)
323; X86-SLM-NEXT:    jne .LBB5_1
324; X86-SLM-NEXT:  # %bb.2: # %atomicrmw.end
325; X86-SLM-NEXT:    retl
326;
327; X86-ATOM-LABEL: and32:
328; X86-ATOM:       # %bb.0:
329; X86-ATOM-NEXT:    movl {{[0-9]+}}(%esp), %ecx
330; X86-ATOM-NEXT:    movl (%ecx), %eax
331; X86-ATOM-NEXT:    .p2align 4, 0x90
332; X86-ATOM-NEXT:  .LBB5_1: # %atomicrmw.start
333; X86-ATOM-NEXT:    # =>This Inner Loop Header: Depth=1
334; X86-ATOM-NEXT:    lock cmpxchgl %eax, (%ecx)
335; X86-ATOM-NEXT:    jne .LBB5_1
336; X86-ATOM-NEXT:  # %bb.2: # %atomicrmw.end
337; X86-ATOM-NEXT:    retl
338  %1 = atomicrmw and ptr %p, i32 -1 acq_rel
339  ret i32 %1
340}
341
342define void @or32_nouse_monotonic(ptr %p) {
343; X64-LABEL: or32_nouse_monotonic:
344; X64:       # %bb.0:
345; X64-NEXT:    #MEMBARRIER
346; X64-NEXT:    retq
347;
348; X86-GENERIC-LABEL: or32_nouse_monotonic:
349; X86-GENERIC:       # %bb.0:
350; X86-GENERIC-NEXT:    #MEMBARRIER
351; X86-GENERIC-NEXT:    retl
352;
353; X86-ATOM-LABEL: or32_nouse_monotonic:
354; X86-ATOM:       # %bb.0:
355; X86-ATOM-NEXT:    #MEMBARRIER
356; X86-ATOM-NEXT:    nop
357; X86-ATOM-NEXT:    nop
358; X86-ATOM-NEXT:    nop
359; X86-ATOM-NEXT:    nop
360; X86-ATOM-NEXT:    nop
361; X86-ATOM-NEXT:    nop
362; X86-ATOM-NEXT:    retl
363  atomicrmw or ptr %p, i32 0 monotonic
364  ret void
365}
366
367
368define void @or32_nouse_acquire(ptr %p) {
369; X64-LABEL: or32_nouse_acquire:
370; X64:       # %bb.0:
371; X64-NEXT:    #MEMBARRIER
372; X64-NEXT:    retq
373;
374; X86-GENERIC-LABEL: or32_nouse_acquire:
375; X86-GENERIC:       # %bb.0:
376; X86-GENERIC-NEXT:    #MEMBARRIER
377; X86-GENERIC-NEXT:    retl
378;
379; X86-ATOM-LABEL: or32_nouse_acquire:
380; X86-ATOM:       # %bb.0:
381; X86-ATOM-NEXT:    #MEMBARRIER
382; X86-ATOM-NEXT:    nop
383; X86-ATOM-NEXT:    nop
384; X86-ATOM-NEXT:    nop
385; X86-ATOM-NEXT:    nop
386; X86-ATOM-NEXT:    nop
387; X86-ATOM-NEXT:    nop
388; X86-ATOM-NEXT:    retl
389  atomicrmw or ptr %p, i32 0 acquire
390  ret void
391}
392
393define void @or32_nouse_release(ptr %p) {
394; X64-LABEL: or32_nouse_release:
395; X64:       # %bb.0:
396; X64-NEXT:    #MEMBARRIER
397; X64-NEXT:    retq
398;
399; X86-GENERIC-LABEL: or32_nouse_release:
400; X86-GENERIC:       # %bb.0:
401; X86-GENERIC-NEXT:    #MEMBARRIER
402; X86-GENERIC-NEXT:    retl
403;
404; X86-ATOM-LABEL: or32_nouse_release:
405; X86-ATOM:       # %bb.0:
406; X86-ATOM-NEXT:    #MEMBARRIER
407; X86-ATOM-NEXT:    nop
408; X86-ATOM-NEXT:    nop
409; X86-ATOM-NEXT:    nop
410; X86-ATOM-NEXT:    nop
411; X86-ATOM-NEXT:    nop
412; X86-ATOM-NEXT:    nop
413; X86-ATOM-NEXT:    retl
414  atomicrmw or ptr %p, i32 0 release
415  ret void
416}
417
418define void @or32_nouse_acq_rel(ptr %p) {
419; X64-LABEL: or32_nouse_acq_rel:
420; X64:       # %bb.0:
421; X64-NEXT:    #MEMBARRIER
422; X64-NEXT:    retq
423;
424; X86-GENERIC-LABEL: or32_nouse_acq_rel:
425; X86-GENERIC:       # %bb.0:
426; X86-GENERIC-NEXT:    #MEMBARRIER
427; X86-GENERIC-NEXT:    retl
428;
429; X86-ATOM-LABEL: or32_nouse_acq_rel:
430; X86-ATOM:       # %bb.0:
431; X86-ATOM-NEXT:    #MEMBARRIER
432; X86-ATOM-NEXT:    nop
433; X86-ATOM-NEXT:    nop
434; X86-ATOM-NEXT:    nop
435; X86-ATOM-NEXT:    nop
436; X86-ATOM-NEXT:    nop
437; X86-ATOM-NEXT:    nop
438; X86-ATOM-NEXT:    retl
439  atomicrmw or ptr %p, i32 0 acq_rel
440  ret void
441}
442
443define void @or32_nouse_seq_cst(ptr %p) {
444; X64-LABEL: or32_nouse_seq_cst:
445; X64:       # %bb.0:
446; X64-NEXT:    lock orl $0, -{{[0-9]+}}(%rsp)
447; X64-NEXT:    retq
448;
449; X86-GENERIC-LABEL: or32_nouse_seq_cst:
450; X86-GENERIC:       # %bb.0:
451; X86-GENERIC-NEXT:    lock orl $0, (%esp)
452; X86-GENERIC-NEXT:    retl
453;
454; X86-ATOM-LABEL: or32_nouse_seq_cst:
455; X86-ATOM:       # %bb.0:
456; X86-ATOM-NEXT:    lock orl $0, (%esp)
457; X86-ATOM-NEXT:    nop
458; X86-ATOM-NEXT:    nop
459; X86-ATOM-NEXT:    nop
460; X86-ATOM-NEXT:    nop
461; X86-ATOM-NEXT:    nop
462; X86-ATOM-NEXT:    nop
463; X86-ATOM-NEXT:    retl
464  atomicrmw or ptr %p, i32 0 seq_cst
465  ret void
466}
467
468; TODO: The value isn't used on 32 bit, so the cmpxchg8b is unneeded
469define void @or64_nouse_seq_cst(ptr %p) {
470; X64-LABEL: or64_nouse_seq_cst:
471; X64:       # %bb.0:
472; X64-NEXT:    lock orl $0, -{{[0-9]+}}(%rsp)
473; X64-NEXT:    retq
474;
475; X86-LABEL: or64_nouse_seq_cst:
476; X86:       # %bb.0:
477; X86-NEXT:    pushl %ebx
478; X86-NEXT:    .cfi_def_cfa_offset 8
479; X86-NEXT:    pushl %esi
480; X86-NEXT:    .cfi_def_cfa_offset 12
481; X86-NEXT:    .cfi_offset %esi, -12
482; X86-NEXT:    .cfi_offset %ebx, -8
483; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
484; X86-NEXT:    movl (%esi), %eax
485; X86-NEXT:    movl 4(%esi), %edx
486; X86-NEXT:    .p2align 4, 0x90
487; X86-NEXT:  .LBB11_1: # %atomicrmw.start
488; X86-NEXT:    # =>This Inner Loop Header: Depth=1
489; X86-NEXT:    movl %edx, %ecx
490; X86-NEXT:    movl %eax, %ebx
491; X86-NEXT:    lock cmpxchg8b (%esi)
492; X86-NEXT:    jne .LBB11_1
493; X86-NEXT:  # %bb.2: # %atomicrmw.end
494; X86-NEXT:    popl %esi
495; X86-NEXT:    .cfi_def_cfa_offset 8
496; X86-NEXT:    popl %ebx
497; X86-NEXT:    .cfi_def_cfa_offset 4
498; X86-NEXT:    retl
499  atomicrmw or ptr %p, i64 0 seq_cst
500  ret void
501}
502
503; TODO: Don't need to lower as sync_and_fetch call
504define void @or128_nouse_seq_cst(ptr %p) {
505; X64-LABEL: or128_nouse_seq_cst:
506; X64:       # %bb.0:
507; X64-NEXT:    pushq %rax
508; X64-NEXT:    .cfi_def_cfa_offset 16
509; X64-NEXT:    xorl %esi, %esi
510; X64-NEXT:    xorl %edx, %edx
511; X64-NEXT:    callq __sync_fetch_and_or_16@PLT
512; X64-NEXT:    popq %rax
513; X64-NEXT:    .cfi_def_cfa_offset 8
514; X64-NEXT:    retq
515;
516; X86-SSE2-LABEL: or128_nouse_seq_cst:
517; X86-SSE2:       # %bb.0:
518; X86-SSE2-NEXT:    pushl %ebp
519; X86-SSE2-NEXT:    .cfi_def_cfa_offset 8
520; X86-SSE2-NEXT:    .cfi_offset %ebp, -8
521; X86-SSE2-NEXT:    movl %esp, %ebp
522; X86-SSE2-NEXT:    .cfi_def_cfa_register %ebp
523; X86-SSE2-NEXT:    andl $-8, %esp
524; X86-SSE2-NEXT:    subl $16, %esp
525; X86-SSE2-NEXT:    movl %esp, %eax
526; X86-SSE2-NEXT:    pushl $0
527; X86-SSE2-NEXT:    pushl $0
528; X86-SSE2-NEXT:    pushl $0
529; X86-SSE2-NEXT:    pushl $0
530; X86-SSE2-NEXT:    pushl 8(%ebp)
531; X86-SSE2-NEXT:    pushl %eax
532; X86-SSE2-NEXT:    calll __sync_fetch_and_or_16
533; X86-SSE2-NEXT:    addl $20, %esp
534; X86-SSE2-NEXT:    movl %ebp, %esp
535; X86-SSE2-NEXT:    popl %ebp
536; X86-SSE2-NEXT:    .cfi_def_cfa %esp, 4
537; X86-SSE2-NEXT:    retl
538;
539; X86-SLM-LABEL: or128_nouse_seq_cst:
540; X86-SLM:       # %bb.0:
541; X86-SLM-NEXT:    pushl %ebp
542; X86-SLM-NEXT:    .cfi_def_cfa_offset 8
543; X86-SLM-NEXT:    .cfi_offset %ebp, -8
544; X86-SLM-NEXT:    movl %esp, %ebp
545; X86-SLM-NEXT:    .cfi_def_cfa_register %ebp
546; X86-SLM-NEXT:    andl $-8, %esp
547; X86-SLM-NEXT:    subl $16, %esp
548; X86-SLM-NEXT:    movl 8(%ebp), %eax
549; X86-SLM-NEXT:    movl %esp, %ecx
550; X86-SLM-NEXT:    pushl $0
551; X86-SLM-NEXT:    pushl $0
552; X86-SLM-NEXT:    pushl $0
553; X86-SLM-NEXT:    pushl $0
554; X86-SLM-NEXT:    pushl %eax
555; X86-SLM-NEXT:    pushl %ecx
556; X86-SLM-NEXT:    calll __sync_fetch_and_or_16
557; X86-SLM-NEXT:    addl $20, %esp
558; X86-SLM-NEXT:    movl %ebp, %esp
559; X86-SLM-NEXT:    popl %ebp
560; X86-SLM-NEXT:    .cfi_def_cfa %esp, 4
561; X86-SLM-NEXT:    retl
562;
563; X86-ATOM-LABEL: or128_nouse_seq_cst:
564; X86-ATOM:       # %bb.0:
565; X86-ATOM-NEXT:    pushl %ebp
566; X86-ATOM-NEXT:    .cfi_def_cfa_offset 8
567; X86-ATOM-NEXT:    .cfi_offset %ebp, -8
568; X86-ATOM-NEXT:    leal (%esp), %ebp
569; X86-ATOM-NEXT:    .cfi_def_cfa_register %ebp
570; X86-ATOM-NEXT:    andl $-8, %esp
571; X86-ATOM-NEXT:    leal -{{[0-9]+}}(%esp), %esp
572; X86-ATOM-NEXT:    movl 8(%ebp), %eax
573; X86-ATOM-NEXT:    movl %esp, %ecx
574; X86-ATOM-NEXT:    pushl $0
575; X86-ATOM-NEXT:    pushl $0
576; X86-ATOM-NEXT:    pushl $0
577; X86-ATOM-NEXT:    pushl $0
578; X86-ATOM-NEXT:    pushl %eax
579; X86-ATOM-NEXT:    pushl %ecx
580; X86-ATOM-NEXT:    calll __sync_fetch_and_or_16
581; X86-ATOM-NEXT:    leal {{[0-9]+}}(%esp), %esp
582; X86-ATOM-NEXT:    movl %ebp, %esp
583; X86-ATOM-NEXT:    popl %ebp
584; X86-ATOM-NEXT:    .cfi_def_cfa %esp, 4
585; X86-ATOM-NEXT:    retl
586  atomicrmw or ptr %p, i128 0 seq_cst
587  ret void
588}
589
590
591define void @or16_nouse_seq_cst(ptr %p) {
592; X64-LABEL: or16_nouse_seq_cst:
593; X64:       # %bb.0:
594; X64-NEXT:    lock orl $0, -{{[0-9]+}}(%rsp)
595; X64-NEXT:    retq
596;
597; X86-GENERIC-LABEL: or16_nouse_seq_cst:
598; X86-GENERIC:       # %bb.0:
599; X86-GENERIC-NEXT:    lock orl $0, (%esp)
600; X86-GENERIC-NEXT:    retl
601;
602; X86-ATOM-LABEL: or16_nouse_seq_cst:
603; X86-ATOM:       # %bb.0:
604; X86-ATOM-NEXT:    lock orl $0, (%esp)
605; X86-ATOM-NEXT:    nop
606; X86-ATOM-NEXT:    nop
607; X86-ATOM-NEXT:    nop
608; X86-ATOM-NEXT:    nop
609; X86-ATOM-NEXT:    nop
610; X86-ATOM-NEXT:    nop
611; X86-ATOM-NEXT:    retl
612  atomicrmw or ptr %p, i16 0 seq_cst
613  ret void
614}
615
616define void @or8_nouse_seq_cst(ptr %p) {
617; X64-LABEL: or8_nouse_seq_cst:
618; X64:       # %bb.0:
619; X64-NEXT:    lock orl $0, -{{[0-9]+}}(%rsp)
620; X64-NEXT:    retq
621;
622; X86-GENERIC-LABEL: or8_nouse_seq_cst:
623; X86-GENERIC:       # %bb.0:
624; X86-GENERIC-NEXT:    lock orl $0, (%esp)
625; X86-GENERIC-NEXT:    retl
626;
627; X86-ATOM-LABEL: or8_nouse_seq_cst:
628; X86-ATOM:       # %bb.0:
629; X86-ATOM-NEXT:    lock orl $0, (%esp)
630; X86-ATOM-NEXT:    nop
631; X86-ATOM-NEXT:    nop
632; X86-ATOM-NEXT:    nop
633; X86-ATOM-NEXT:    nop
634; X86-ATOM-NEXT:    nop
635; X86-ATOM-NEXT:    nop
636; X86-ATOM-NEXT:    retl
637  atomicrmw or ptr %p, i8 0 seq_cst
638  ret void
639}
640