1; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2  < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
2; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=avx  < %s | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
3
4declare float @fmaxf(float, float)
5declare double @fmax(double, double)
6declare x86_fp80 @fmaxl(x86_fp80, x86_fp80)
7declare float @llvm.maxnum.f32(float, float)
8declare double @llvm.maxnum.f64(double, double)
9declare x86_fp80 @llvm.maxnum.f80(x86_fp80, x86_fp80)
10
11declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
12declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>)
13declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)
14declare <4 x double> @llvm.maxnum.v4f64(<4 x double>, <4 x double>)
15declare <8 x double> @llvm.maxnum.v8f64(<8 x double>, <8 x double>)
16
17
18; CHECK-LABEL: @test_fmaxf
19; CHECK: jmp fmaxf
20define float @test_fmaxf(float %x, float %y) {
21  %z = call float @fmaxf(float %x, float %y) readnone
22  ret float %z
23}
24
25; CHECK-LABEL: @test_fmax
26; CHECK: jmp fmax
27define double @test_fmax(double %x, double %y) {
28  %z = call double @fmax(double %x, double %y) readnone
29  ret double %z
30}
31
32; CHECK-LABEL: @test_fmaxl
33; CHECK: callq fmaxl
34define x86_fp80 @test_fmaxl(x86_fp80 %x, x86_fp80 %y) {
35  %z = call x86_fp80 @fmaxl(x86_fp80 %x, x86_fp80 %y) readnone
36  ret x86_fp80 %z
37}
38
39; CHECK-LABEL: @test_intrinsic_fmaxf
40; CHECK: jmp fmaxf
41define float @test_intrinsic_fmaxf(float %x, float %y) {
42  %z = call float @llvm.maxnum.f32(float %x, float %y) readnone
43  ret float %z
44}
45
46; CHECK-LABEL: @test_intrinsic_fmax
47; CHECK: jmp fmax
48define double @test_intrinsic_fmax(double %x, double %y) {
49  %z = call double @llvm.maxnum.f64(double %x, double %y) readnone
50  ret double %z
51}
52
53; CHECK-LABEL: @test_intrinsic_fmaxl
54; CHECK: callq fmaxl
55define x86_fp80 @test_intrinsic_fmaxl(x86_fp80 %x, x86_fp80 %y) {
56  %z = call x86_fp80 @llvm.maxnum.f80(x86_fp80 %x, x86_fp80 %y) readnone
57  ret x86_fp80 %z
58}
59
60; CHECK-LABEL: @test_intrinsic_fmax_v2f32
61; SSE:         movaps %xmm1, {{[0-9]+}}(%rsp) # 16-byte Spill
62; SSE-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
63; SSE-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
64; SSE-NEXT:    shufps {{.*#+}} xmm1 = xmm1[3,1,2,3]
65; SSE-NEXT:    callq fmaxf
66; SSE-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
67; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
68; SSE-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
69; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
70; SSE-NEXT:    shufps {{.*#+}} xmm1 = xmm1[1,1,2,3]
71; SSE-NEXT:    callq fmaxf
72; SSE-NEXT:    unpcklps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
73; SSE:         movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
74; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
75; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
76; SSE-NEXT:    callq fmaxf
77; SSE-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
78; SSE-NEXT:    movapd {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
79; SSE-NEXT:    shufpd {{.*#+}} xmm0 = xmm0[1,0]
80; SSE-NEXT:    movapd {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
81; SSE-NEXT:    shufpd {{.*#+}} xmm1 = xmm1[1,0]
82; SSE-NEXT:    callq fmaxf
83; SSE-NEXT:    movaps (%rsp), %xmm1 # 16-byte Reload
84; SSE-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
85; SSE-NEXT:    unpcklps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
86; SSE:         movaps %xmm1, %xmm0
87; SSE-NEXT:    addq $72, %rsp
88; SSE-NEXT:    retq
89;
90; AVX:         vmovaps %xmm1, {{[0-9]+}}(%rsp) # 16-byte Spill
91; AVX-NEXT:    vmovaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
92; AVX-NEXT:    callq fmaxf
93; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
94; AVX-NEXT:    vmovshdup {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
95; AVX:         vmovshdup {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
96; AVX:         callq fmaxf
97; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
98; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3]
99; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
100; AVX-NEXT:    vpermilpd $1, {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
101; AVX:         vpermilpd $1, {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
102; AVX:         callq fmaxf
103; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
104; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0,1],xmm0[0],xmm1[3]
105; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
106; AVX-NEXT:    vpermilps $231, {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
107; AVX:         vpermilps $231, {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
108; AVX:         callq fmaxf
109; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
110; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0]
111; AVX-NEXT:    addq $56, %rsp
112; AVX-NEXT:    retq
113define <2 x float> @test_intrinsic_fmax_v2f32(<2 x float> %x, <2 x float> %y) {
114  %z = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> %y) readnone
115  ret <2 x float> %z
116}
117
118; CHECK-LABEL: @test_intrinsic_fmax_v4f32
119; SSE:         movaps %xmm1, {{[0-9]+}}(%rsp) # 16-byte Spill
120; SSE-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
121; SSE-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
122; SSE-NEXT:    shufps {{.*#+}} xmm1 = xmm1[3,1,2,3]
123; SSE-NEXT:    callq fmaxf
124; SSE-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
125; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
126; SSE-NEXT:    shufps {{.*#+}} xmm0 = xmm0[1,1,2,3]
127; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
128; SSE-NEXT:    shufps {{.*#+}} xmm1 = xmm1[1,1,2,3]
129; SSE-NEXT:    callq fmaxf
130; SSE-NEXT:    unpcklps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
131; SSE:         movaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
132; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
133; SSE-NEXT:    movaps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
134; SSE-NEXT:    callq fmaxf
135; SSE-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
136; SSE-NEXT:    movapd {{[0-9]+}}(%rsp), %xmm0 # 16-byte Reload
137; SSE-NEXT:    shufpd {{.*#+}} xmm0 = xmm0[1,0]
138; SSE-NEXT:    movapd {{[0-9]+}}(%rsp), %xmm1 # 16-byte Reload
139; SSE-NEXT:    shufpd {{.*#+}} xmm1 = xmm1[1,0]
140; SSE-NEXT:    callq fmaxf
141; SSE-NEXT:    movaps (%rsp), %xmm1 # 16-byte Reload
142; SSE-NEXT:    unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
143; SSE-NEXT:    unpcklps {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
144; SSE:         movaps %xmm1, %xmm0
145; SSE-NEXT:    addq $72, %rsp
146; SSE-NEXT:    retq
147;
148; AVX:         vmovaps %xmm1, {{[0-9]+}}(%rsp) # 16-byte Spill
149; AVX-NEXT:    vmovaps %xmm0, {{[0-9]+}}(%rsp) # 16-byte Spill
150; AVX-NEXT:    callq fmaxf
151; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
152; AVX-NEXT:    vmovshdup {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
153; AVX:         vmovshdup {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
154; AVX:         callq fmaxf
155; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
156; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3]
157; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
158; AVX-NEXT:    vpermilpd $1, {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
159; AVX:         vpermilpd $1, {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
160; AVX:         callq fmaxf
161; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
162; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0,1],xmm0[0],xmm1[3]
163; AVX-NEXT:    vmovaps %xmm0, (%rsp) # 16-byte Spill
164; AVX-NEXT:    vpermilps $231, {{[0-9]+}}(%rsp), %xmm0 # 16-byte Folded Reload
165; AVX:         vpermilps $231, {{[0-9]+}}(%rsp), %xmm1 # 16-byte Folded Reload
166; AVX:         callq fmaxf
167; AVX-NEXT:    vmovaps (%rsp), %xmm1 # 16-byte Reload
168; AVX-NEXT:    vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0]
169; AVX-NEXT:    addq $56, %rsp
170; AVX-NEXT:    retq
171define <4 x float> @test_intrinsic_fmax_v4f32(<4 x float> %x, <4 x float> %y) {
172  %z = call <4 x float> @llvm.maxnum.v4f32(<4 x float> %x, <4 x float> %y) readnone
173  ret <4 x float> %z
174}
175
176; CHECK-LABEL: @test_intrinsic_fmax_v2f64
177; CHECK: callq fmax
178; CHECK: callq fmax
179define <2 x double> @test_intrinsic_fmax_v2f64(<2 x double> %x, <2 x double> %y) {
180  %z = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> %y) readnone
181  ret <2 x double> %z
182}
183
184; CHECK-LABEL: @test_intrinsic_fmax_v4f64
185; CHECK: callq fmax
186; CHECK: callq fmax
187; CHECK: callq fmax
188; CHECK: callq fmax
189define <4 x double> @test_intrinsic_fmax_v4f64(<4 x double> %x, <4 x double> %y) {
190  %z = call <4 x double> @llvm.maxnum.v4f64(<4 x double> %x, <4 x double> %y) readnone
191  ret <4 x double> %z
192}
193
194; CHECK-LABEL: @test_intrinsic_fmax_v8f64
195; CHECK: callq fmax
196; CHECK: callq fmax
197; CHECK: callq fmax
198; CHECK: callq fmax
199; CHECK: callq fmax
200; CHECK: callq fmax
201; CHECK: callq fmax
202; CHECK: callq fmax
203define <8 x double> @test_intrinsic_fmax_v8f64(<8 x double> %x, <8 x double> %y) {
204  %z = call <8 x double> @llvm.maxnum.v8f64(<8 x double> %x, <8 x double> %y) readnone
205  ret <8 x double> %z
206}
207
208