1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-linux-generic -verify-machineinstrs -mattr=sse2 | FileCheck %s
3
4; Note: This test is testing that the lowering for atomics matches what we
5; currently emit for non-atomics + the atomic restriction.  The presence of
6; particular lowering detail in these tests should not be read as requiring
7; that detail for correctness unless it's related to the atomicity itself.
8; (Specifically, there were reviewer questions about the lowering for halfs
9;  and their calling convention which remain unresolved.)
10
11define void @store_half(half* %fptr, half %v) {
12; CHECK-LABEL: store_half:
13; CHECK:       # %bb.0:
14; CHECK-NEXT:    pushq %rbx
15; CHECK-NEXT:    .cfi_def_cfa_offset 16
16; CHECK-NEXT:    .cfi_offset %rbx, -16
17; CHECK-NEXT:    movq %rdi, %rbx
18; CHECK-NEXT:    callq __gnu_f2h_ieee
19; CHECK-NEXT:    movw %ax, (%rbx)
20; CHECK-NEXT:    popq %rbx
21; CHECK-NEXT:    .cfi_def_cfa_offset 8
22; CHECK-NEXT:    retq
23  store atomic half %v, half* %fptr unordered, align 2
24  ret void
25}
26
27define void @store_float(float* %fptr, float %v) {
28; CHECK-LABEL: store_float:
29; CHECK:       # %bb.0:
30; CHECK-NEXT:    movd %xmm0, %eax
31; CHECK-NEXT:    movl %eax, (%rdi)
32; CHECK-NEXT:    retq
33  store atomic float %v, float* %fptr unordered, align 4
34  ret void
35}
36
37define void @store_double(double* %fptr, double %v) {
38; CHECK-LABEL: store_double:
39; CHECK:       # %bb.0:
40; CHECK-NEXT:    movq %xmm0, %rax
41; CHECK-NEXT:    movq %rax, (%rdi)
42; CHECK-NEXT:    retq
43  store atomic double %v, double* %fptr unordered, align 8
44  ret void
45}
46
47define void @store_fp128(fp128* %fptr, fp128 %v) {
48; CHECK-LABEL: store_fp128:
49; CHECK:       # %bb.0:
50; CHECK-NEXT:    pushq %rax
51; CHECK-NEXT:    .cfi_def_cfa_offset 16
52; CHECK-NEXT:    callq __sync_lock_test_and_set_16
53; CHECK-NEXT:    popq %rax
54; CHECK-NEXT:    .cfi_def_cfa_offset 8
55; CHECK-NEXT:    retq
56  store atomic fp128 %v, fp128* %fptr unordered, align 16
57  ret void
58}
59
60define half @load_half(half* %fptr) {
61; CHECK-LABEL: load_half:
62; CHECK:       # %bb.0:
63; CHECK-NEXT:    pushq %rax
64; CHECK-NEXT:    .cfi_def_cfa_offset 16
65; CHECK-NEXT:    movzwl (%rdi), %eax
66; CHECK-NEXT:    movzwl %ax, %edi
67; CHECK-NEXT:    callq __gnu_h2f_ieee
68; CHECK-NEXT:    popq %rax
69; CHECK-NEXT:    .cfi_def_cfa_offset 8
70; CHECK-NEXT:    retq
71  %v = load atomic half, half* %fptr unordered, align 2
72  ret half %v
73}
74
75define float @load_float(float* %fptr) {
76; CHECK-LABEL: load_float:
77; CHECK:       # %bb.0:
78; CHECK-NEXT:    movl (%rdi), %eax
79; CHECK-NEXT:    movd %eax, %xmm0
80; CHECK-NEXT:    retq
81  %v = load atomic float, float* %fptr unordered, align 4
82  ret float %v
83}
84
85define double @load_double(double* %fptr) {
86; CHECK-LABEL: load_double:
87; CHECK:       # %bb.0:
88; CHECK-NEXT:    movq (%rdi), %rax
89; CHECK-NEXT:    movq %rax, %xmm0
90; CHECK-NEXT:    retq
91  %v = load atomic double, double* %fptr unordered, align 8
92  ret double %v
93}
94
95define fp128 @load_fp128(fp128* %fptr) {
96; CHECK-LABEL: load_fp128:
97; CHECK:       # %bb.0:
98; CHECK-NEXT:    pushq %rax
99; CHECK-NEXT:    .cfi_def_cfa_offset 16
100; CHECK-NEXT:    xorl %esi, %esi
101; CHECK-NEXT:    xorl %edx, %edx
102; CHECK-NEXT:    xorl %ecx, %ecx
103; CHECK-NEXT:    xorl %r8d, %r8d
104; CHECK-NEXT:    callq __sync_val_compare_and_swap_16
105; CHECK-NEXT:    popq %rcx
106; CHECK-NEXT:    .cfi_def_cfa_offset 8
107; CHECK-NEXT:    retq
108  %v = load atomic fp128, fp128* %fptr unordered, align 16
109  ret fp128 %v
110}
111
112
113; sanity check the seq_cst lowering since that's the
114; interesting one from an ordering perspective on x86.
115
116define void @store_float_seq_cst(float* %fptr, float %v) {
117; CHECK-LABEL: store_float_seq_cst:
118; CHECK:       # %bb.0:
119; CHECK-NEXT:    movd %xmm0, %eax
120; CHECK-NEXT:    xchgl %eax, (%rdi)
121; CHECK-NEXT:    retq
122  store atomic float %v, float* %fptr seq_cst, align 4
123  ret void
124}
125
126define void @store_double_seq_cst(double* %fptr, double %v) {
127; CHECK-LABEL: store_double_seq_cst:
128; CHECK:       # %bb.0:
129; CHECK-NEXT:    movq %xmm0, %rax
130; CHECK-NEXT:    xchgq %rax, (%rdi)
131; CHECK-NEXT:    retq
132  store atomic double %v, double* %fptr seq_cst, align 8
133  ret void
134}
135
136define float @load_float_seq_cst(float* %fptr) {
137; CHECK-LABEL: load_float_seq_cst:
138; CHECK:       # %bb.0:
139; CHECK-NEXT:    movl (%rdi), %eax
140; CHECK-NEXT:    movd %eax, %xmm0
141; CHECK-NEXT:    retq
142  %v = load atomic float, float* %fptr seq_cst, align 4
143  ret float %v
144}
145
146define double @load_double_seq_cst(double* %fptr) {
147; CHECK-LABEL: load_double_seq_cst:
148; CHECK:       # %bb.0:
149; CHECK-NEXT:    movq (%rdi), %rax
150; CHECK-NEXT:    movq %rax, %xmm0
151; CHECK-NEXT:    retq
152  %v = load atomic double, double* %fptr seq_cst, align 8
153  ret double %v
154}
155