1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2    | FileCheck %s --check-prefixes=SSE,SSE2
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1  | FileCheck %s --check-prefixes=SSE,SSE41
4; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx     | FileCheck %s --check-prefixes=AVX1
5
6define float @trunc_unsigned_f32(float %x) #0 {
7; SSE2-LABEL: trunc_unsigned_f32:
8; SSE2:       # %bb.0:
9; SSE2-NEXT:    cvttss2si %xmm0, %rax
10; SSE2-NEXT:    movl %eax, %eax
11; SSE2-NEXT:    xorps %xmm0, %xmm0
12; SSE2-NEXT:    cvtsi2ss %rax, %xmm0
13; SSE2-NEXT:    retq
14;
15; SSE41-LABEL: trunc_unsigned_f32:
16; SSE41:       # %bb.0:
17; SSE41-NEXT:    roundss $11, %xmm0, %xmm0
18; SSE41-NEXT:    retq
19;
20; AVX1-LABEL: trunc_unsigned_f32:
21; AVX1:       # %bb.0:
22; AVX1-NEXT:    vroundss $11, %xmm0, %xmm0, %xmm0
23; AVX1-NEXT:    retq
24  %i = fptoui float %x to i32
25  %r = uitofp i32 %i to float
26  ret float %r
27}
28
29define double @trunc_unsigned_f64(double %x) #0 {
30; SSE2-LABEL: trunc_unsigned_f64:
31; SSE2:       # %bb.0:
32; SSE2-NEXT:    movsd {{.*#+}} xmm1 = mem[0],zero
33; SSE2-NEXT:    movapd %xmm0, %xmm2
34; SSE2-NEXT:    subsd %xmm1, %xmm2
35; SSE2-NEXT:    cvttsd2si %xmm2, %rax
36; SSE2-NEXT:    movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
37; SSE2-NEXT:    xorq %rax, %rcx
38; SSE2-NEXT:    cvttsd2si %xmm0, %rax
39; SSE2-NEXT:    ucomisd %xmm1, %xmm0
40; SSE2-NEXT:    cmovaeq %rcx, %rax
41; SSE2-NEXT:    movq %rax, %xmm1
42; SSE2-NEXT:    punpckldq {{.*#+}} xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
43; SSE2-NEXT:    subpd {{.*}}(%rip), %xmm1
44; SSE2-NEXT:    movapd %xmm1, %xmm0
45; SSE2-NEXT:    unpckhpd {{.*#+}} xmm0 = xmm0[1],xmm1[1]
46; SSE2-NEXT:    addsd %xmm1, %xmm0
47; SSE2-NEXT:    retq
48;
49; SSE41-LABEL: trunc_unsigned_f64:
50; SSE41:       # %bb.0:
51; SSE41-NEXT:    roundsd $11, %xmm0, %xmm0
52; SSE41-NEXT:    retq
53;
54; AVX1-LABEL: trunc_unsigned_f64:
55; AVX1:       # %bb.0:
56; AVX1-NEXT:    vroundsd $11, %xmm0, %xmm0, %xmm0
57; AVX1-NEXT:    retq
58  %i = fptoui double %x to i64
59  %r = uitofp i64 %i to double
60  ret double %r
61}
62
63define <4 x float> @trunc_unsigned_v4f32(<4 x float> %x) #0 {
64; SSE2-LABEL: trunc_unsigned_v4f32:
65; SSE2:       # %bb.0:
66; SSE2-NEXT:    movaps {{.*#+}} xmm2 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9]
67; SSE2-NEXT:    movaps %xmm0, %xmm1
68; SSE2-NEXT:    cmpltps %xmm2, %xmm1
69; SSE2-NEXT:    cvttps2dq %xmm0, %xmm3
70; SSE2-NEXT:    subps %xmm2, %xmm0
71; SSE2-NEXT:    cvttps2dq %xmm0, %xmm0
72; SSE2-NEXT:    xorps {{.*}}(%rip), %xmm0
73; SSE2-NEXT:    andps %xmm1, %xmm3
74; SSE2-NEXT:    andnps %xmm0, %xmm1
75; SSE2-NEXT:    orps %xmm3, %xmm1
76; SSE2-NEXT:    movaps {{.*#+}} xmm0 = [65535,65535,65535,65535]
77; SSE2-NEXT:    andps %xmm1, %xmm0
78; SSE2-NEXT:    orps {{.*}}(%rip), %xmm0
79; SSE2-NEXT:    psrld $16, %xmm1
80; SSE2-NEXT:    por {{.*}}(%rip), %xmm1
81; SSE2-NEXT:    subps {{.*}}(%rip), %xmm1
82; SSE2-NEXT:    addps %xmm0, %xmm1
83; SSE2-NEXT:    movaps %xmm1, %xmm0
84; SSE2-NEXT:    retq
85;
86; SSE41-LABEL: trunc_unsigned_v4f32:
87; SSE41:       # %bb.0:
88; SSE41-NEXT:    roundps $11, %xmm0, %xmm0
89; SSE41-NEXT:    retq
90;
91; AVX1-LABEL: trunc_unsigned_v4f32:
92; AVX1:       # %bb.0:
93; AVX1-NEXT:    vroundps $11, %xmm0, %xmm0
94; AVX1-NEXT:    retq
95  %i = fptoui <4 x float> %x to <4 x i32>
96  %r = uitofp <4 x i32> %i to <4 x float>
97  ret <4 x float> %r
98}
99
100define <2 x double> @trunc_unsigned_v2f64(<2 x double> %x) #0 {
101; SSE2-LABEL: trunc_unsigned_v2f64:
102; SSE2:       # %bb.0:
103; SSE2-NEXT:    movsd {{.*#+}} xmm2 = mem[0],zero
104; SSE2-NEXT:    movapd %xmm0, %xmm1
105; SSE2-NEXT:    subsd %xmm2, %xmm1
106; SSE2-NEXT:    cvttsd2si %xmm1, %rax
107; SSE2-NEXT:    movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
108; SSE2-NEXT:    xorq %rcx, %rax
109; SSE2-NEXT:    cvttsd2si %xmm0, %rdx
110; SSE2-NEXT:    ucomisd %xmm2, %xmm0
111; SSE2-NEXT:    cmovaeq %rax, %rdx
112; SSE2-NEXT:    movq %rdx, %xmm1
113; SSE2-NEXT:    unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
114; SSE2-NEXT:    movapd %xmm0, %xmm3
115; SSE2-NEXT:    subsd %xmm2, %xmm3
116; SSE2-NEXT:    cvttsd2si %xmm3, %rax
117; SSE2-NEXT:    xorq %rcx, %rax
118; SSE2-NEXT:    cvttsd2si %xmm0, %rcx
119; SSE2-NEXT:    ucomisd %xmm2, %xmm0
120; SSE2-NEXT:    cmovaeq %rax, %rcx
121; SSE2-NEXT:    movq %rcx, %xmm0
122; SSE2-NEXT:    punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
123; SSE2-NEXT:    movdqa {{.*#+}} xmm0 = [4294967295,4294967295]
124; SSE2-NEXT:    pand %xmm1, %xmm0
125; SSE2-NEXT:    por {{.*}}(%rip), %xmm0
126; SSE2-NEXT:    psrlq $32, %xmm1
127; SSE2-NEXT:    por {{.*}}(%rip), %xmm1
128; SSE2-NEXT:    subpd {{.*}}(%rip), %xmm1
129; SSE2-NEXT:    addpd %xmm0, %xmm1
130; SSE2-NEXT:    movapd %xmm1, %xmm0
131; SSE2-NEXT:    retq
132;
133; SSE41-LABEL: trunc_unsigned_v2f64:
134; SSE41:       # %bb.0:
135; SSE41-NEXT:    roundpd $11, %xmm0, %xmm0
136; SSE41-NEXT:    retq
137;
138; AVX1-LABEL: trunc_unsigned_v2f64:
139; AVX1:       # %bb.0:
140; AVX1-NEXT:    vroundpd $11, %xmm0, %xmm0
141; AVX1-NEXT:    retq
142  %i = fptoui <2 x double> %x to <2 x i64>
143  %r = uitofp <2 x i64> %i to <2 x double>
144  ret <2 x double> %r
145}
146
147define <4 x double> @trunc_unsigned_v4f64(<4 x double> %x) #0 {
148; SSE2-LABEL: trunc_unsigned_v4f64:
149; SSE2:       # %bb.0:
150; SSE2-NEXT:    movapd %xmm1, %xmm2
151; SSE2-NEXT:    movsd {{.*#+}} xmm3 = mem[0],zero
152; SSE2-NEXT:    subsd %xmm3, %xmm1
153; SSE2-NEXT:    cvttsd2si %xmm1, %rcx
154; SSE2-NEXT:    movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
155; SSE2-NEXT:    xorq %rax, %rcx
156; SSE2-NEXT:    cvttsd2si %xmm2, %rdx
157; SSE2-NEXT:    ucomisd %xmm3, %xmm2
158; SSE2-NEXT:    cmovaeq %rcx, %rdx
159; SSE2-NEXT:    movq %rdx, %xmm1
160; SSE2-NEXT:    unpckhpd {{.*#+}} xmm2 = xmm2[1,1]
161; SSE2-NEXT:    movapd %xmm2, %xmm4
162; SSE2-NEXT:    subsd %xmm3, %xmm4
163; SSE2-NEXT:    cvttsd2si %xmm4, %rcx
164; SSE2-NEXT:    xorq %rax, %rcx
165; SSE2-NEXT:    cvttsd2si %xmm2, %rdx
166; SSE2-NEXT:    ucomisd %xmm3, %xmm2
167; SSE2-NEXT:    cmovaeq %rcx, %rdx
168; SSE2-NEXT:    movq %rdx, %xmm2
169; SSE2-NEXT:    punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
170; SSE2-NEXT:    movapd %xmm0, %xmm2
171; SSE2-NEXT:    subsd %xmm3, %xmm2
172; SSE2-NEXT:    cvttsd2si %xmm2, %rcx
173; SSE2-NEXT:    xorq %rax, %rcx
174; SSE2-NEXT:    cvttsd2si %xmm0, %rdx
175; SSE2-NEXT:    ucomisd %xmm3, %xmm0
176; SSE2-NEXT:    cmovaeq %rcx, %rdx
177; SSE2-NEXT:    movq %rdx, %xmm2
178; SSE2-NEXT:    unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
179; SSE2-NEXT:    movapd %xmm0, %xmm4
180; SSE2-NEXT:    subsd %xmm3, %xmm4
181; SSE2-NEXT:    cvttsd2si %xmm4, %rcx
182; SSE2-NEXT:    xorq %rax, %rcx
183; SSE2-NEXT:    cvttsd2si %xmm0, %rax
184; SSE2-NEXT:    ucomisd %xmm3, %xmm0
185; SSE2-NEXT:    cmovaeq %rcx, %rax
186; SSE2-NEXT:    movq %rax, %xmm0
187; SSE2-NEXT:    punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0]
188; SSE2-NEXT:    movdqa {{.*#+}} xmm0 = [4294967295,4294967295]
189; SSE2-NEXT:    movdqa %xmm2, %xmm3
190; SSE2-NEXT:    pand %xmm0, %xmm3
191; SSE2-NEXT:    movdqa {{.*#+}} xmm4 = [4841369599423283200,4841369599423283200]
192; SSE2-NEXT:    por %xmm4, %xmm3
193; SSE2-NEXT:    psrlq $32, %xmm2
194; SSE2-NEXT:    movdqa {{.*#+}} xmm5 = [4985484787499139072,4985484787499139072]
195; SSE2-NEXT:    por %xmm5, %xmm2
196; SSE2-NEXT:    movapd {{.*#+}} xmm6 = [1.9342813118337666E+25,1.9342813118337666E+25]
197; SSE2-NEXT:    subpd %xmm6, %xmm2
198; SSE2-NEXT:    addpd %xmm3, %xmm2
199; SSE2-NEXT:    pand %xmm1, %xmm0
200; SSE2-NEXT:    por %xmm4, %xmm0
201; SSE2-NEXT:    psrlq $32, %xmm1
202; SSE2-NEXT:    por %xmm5, %xmm1
203; SSE2-NEXT:    subpd %xmm6, %xmm1
204; SSE2-NEXT:    addpd %xmm0, %xmm1
205; SSE2-NEXT:    movapd %xmm2, %xmm0
206; SSE2-NEXT:    retq
207;
208; SSE41-LABEL: trunc_unsigned_v4f64:
209; SSE41:       # %bb.0:
210; SSE41-NEXT:    roundpd $11, %xmm0, %xmm0
211; SSE41-NEXT:    roundpd $11, %xmm1, %xmm1
212; SSE41-NEXT:    retq
213;
214; AVX1-LABEL: trunc_unsigned_v4f64:
215; AVX1:       # %bb.0:
216; AVX1-NEXT:    vroundpd $11, %ymm0, %ymm0
217; AVX1-NEXT:    retq
218  %i = fptoui <4 x double> %x to <4 x i64>
219  %r = uitofp <4 x i64> %i to <4 x double>
220  ret <4 x double> %r
221}
222
223define float @trunc_signed_f32_no_fast_math(float %x) {
224; SSE-LABEL: trunc_signed_f32_no_fast_math:
225; SSE:       # %bb.0:
226; SSE-NEXT:    cvttps2dq %xmm0, %xmm0
227; SSE-NEXT:    cvtdq2ps %xmm0, %xmm0
228; SSE-NEXT:    retq
229;
230; AVX1-LABEL: trunc_signed_f32_no_fast_math:
231; AVX1:       # %bb.0:
232; AVX1-NEXT:    vcvttps2dq %xmm0, %xmm0
233; AVX1-NEXT:    vcvtdq2ps %xmm0, %xmm0
234; AVX1-NEXT:    retq
235  %i = fptosi float %x to i32
236  %r = sitofp i32 %i to float
237  ret float %r
238}
239
240define float @trunc_signed_f32(float %x) #0 {
241; SSE2-LABEL: trunc_signed_f32:
242; SSE2:       # %bb.0:
243; SSE2-NEXT:    cvttps2dq %xmm0, %xmm0
244; SSE2-NEXT:    cvtdq2ps %xmm0, %xmm0
245; SSE2-NEXT:    retq
246;
247; SSE41-LABEL: trunc_signed_f32:
248; SSE41:       # %bb.0:
249; SSE41-NEXT:    roundss $11, %xmm0, %xmm0
250; SSE41-NEXT:    retq
251;
252; AVX1-LABEL: trunc_signed_f32:
253; AVX1:       # %bb.0:
254; AVX1-NEXT:    vroundss $11, %xmm0, %xmm0, %xmm0
255; AVX1-NEXT:    retq
256  %i = fptosi float %x to i32
257  %r = sitofp i32 %i to float
258  ret float %r
259}
260
261define double @trunc_signed_f64(double %x) #0 {
262; SSE2-LABEL: trunc_signed_f64:
263; SSE2:       # %bb.0:
264; SSE2-NEXT:    cvttsd2si %xmm0, %rax
265; SSE2-NEXT:    xorps %xmm0, %xmm0
266; SSE2-NEXT:    cvtsi2sd %rax, %xmm0
267; SSE2-NEXT:    retq
268;
269; SSE41-LABEL: trunc_signed_f64:
270; SSE41:       # %bb.0:
271; SSE41-NEXT:    roundsd $11, %xmm0, %xmm0
272; SSE41-NEXT:    retq
273;
274; AVX1-LABEL: trunc_signed_f64:
275; AVX1:       # %bb.0:
276; AVX1-NEXT:    vroundsd $11, %xmm0, %xmm0, %xmm0
277; AVX1-NEXT:    retq
278  %i = fptosi double %x to i64
279  %r = sitofp i64 %i to double
280  ret double %r
281}
282
283define <4 x float> @trunc_signed_v4f32(<4 x float> %x) #0 {
284; SSE2-LABEL: trunc_signed_v4f32:
285; SSE2:       # %bb.0:
286; SSE2-NEXT:    cvttps2dq %xmm0, %xmm0
287; SSE2-NEXT:    cvtdq2ps %xmm0, %xmm0
288; SSE2-NEXT:    retq
289;
290; SSE41-LABEL: trunc_signed_v4f32:
291; SSE41:       # %bb.0:
292; SSE41-NEXT:    roundps $11, %xmm0, %xmm0
293; SSE41-NEXT:    retq
294;
295; AVX1-LABEL: trunc_signed_v4f32:
296; AVX1:       # %bb.0:
297; AVX1-NEXT:    vroundps $11, %xmm0, %xmm0
298; AVX1-NEXT:    retq
299  %i = fptosi <4 x float> %x to <4 x i32>
300  %r = sitofp <4 x i32> %i to <4 x float>
301  ret <4 x float> %r
302}
303
304define <2 x double> @trunc_signed_v2f64(<2 x double> %x) #0 {
305; SSE2-LABEL: trunc_signed_v2f64:
306; SSE2:       # %bb.0:
307; SSE2-NEXT:    cvttsd2si %xmm0, %rax
308; SSE2-NEXT:    unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
309; SSE2-NEXT:    cvttsd2si %xmm0, %rcx
310; SSE2-NEXT:    xorps %xmm0, %xmm0
311; SSE2-NEXT:    cvtsi2sd %rax, %xmm0
312; SSE2-NEXT:    cvtsi2sd %rcx, %xmm1
313; SSE2-NEXT:    unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0]
314; SSE2-NEXT:    retq
315;
316; SSE41-LABEL: trunc_signed_v2f64:
317; SSE41:       # %bb.0:
318; SSE41-NEXT:    roundpd $11, %xmm0, %xmm0
319; SSE41-NEXT:    retq
320;
321; AVX1-LABEL: trunc_signed_v2f64:
322; AVX1:       # %bb.0:
323; AVX1-NEXT:    vroundpd $11, %xmm0, %xmm0
324; AVX1-NEXT:    retq
325  %i = fptosi <2 x double> %x to <2 x i64>
326  %r = sitofp <2 x i64> %i to <2 x double>
327  ret <2 x double> %r
328}
329
330define <4 x double> @trunc_signed_v4f64(<4 x double> %x) #0 {
331; SSE2-LABEL: trunc_signed_v4f64:
332; SSE2:       # %bb.0:
333; SSE2-NEXT:    cvttsd2si %xmm1, %rax
334; SSE2-NEXT:    unpckhpd {{.*#+}} xmm1 = xmm1[1,1]
335; SSE2-NEXT:    cvttsd2si %xmm1, %rcx
336; SSE2-NEXT:    cvttsd2si %xmm0, %rdx
337; SSE2-NEXT:    unpckhpd {{.*#+}} xmm0 = xmm0[1,1]
338; SSE2-NEXT:    cvttsd2si %xmm0, %rsi
339; SSE2-NEXT:    xorps %xmm0, %xmm0
340; SSE2-NEXT:    cvtsi2sd %rdx, %xmm0
341; SSE2-NEXT:    xorps %xmm1, %xmm1
342; SSE2-NEXT:    cvtsi2sd %rsi, %xmm1
343; SSE2-NEXT:    unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0]
344; SSE2-NEXT:    xorps %xmm1, %xmm1
345; SSE2-NEXT:    cvtsi2sd %rax, %xmm1
346; SSE2-NEXT:    cvtsi2sd %rcx, %xmm2
347; SSE2-NEXT:    unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0]
348; SSE2-NEXT:    retq
349;
350; SSE41-LABEL: trunc_signed_v4f64:
351; SSE41:       # %bb.0:
352; SSE41-NEXT:    roundpd $11, %xmm0, %xmm0
353; SSE41-NEXT:    roundpd $11, %xmm1, %xmm1
354; SSE41-NEXT:    retq
355;
356; AVX1-LABEL: trunc_signed_v4f64:
357; AVX1:       # %bb.0:
358; AVX1-NEXT:    vroundpd $11, %ymm0, %ymm0
359; AVX1-NEXT:    retq
360  %i = fptosi <4 x double> %x to <4 x i64>
361  %r = sitofp <4 x i64> %i to <4 x double>
362  ret <4 x double> %r
363}
364
365; The fold may be guarded to allow existing code to continue
366; working based on its assumptions of float->int overflow.
367
368define float @trunc_unsigned_f32_disable_via_attr(float %x) #1 {
369; SSE-LABEL: trunc_unsigned_f32_disable_via_attr:
370; SSE:       # %bb.0:
371; SSE-NEXT:    cvttss2si %xmm0, %rax
372; SSE-NEXT:    movl %eax, %eax
373; SSE-NEXT:    xorps %xmm0, %xmm0
374; SSE-NEXT:    cvtsi2ss %rax, %xmm0
375; SSE-NEXT:    retq
376;
377; AVX1-LABEL: trunc_unsigned_f32_disable_via_attr:
378; AVX1:       # %bb.0:
379; AVX1-NEXT:    vcvttss2si %xmm0, %rax
380; AVX1-NEXT:    movl %eax, %eax
381; AVX1-NEXT:    vcvtsi2ss %rax, %xmm1, %xmm0
382; AVX1-NEXT:    retq
383  %i = fptoui float %x to i32
384  %r = uitofp i32 %i to float
385  ret float %r
386}
387
388define double @trunc_signed_f64_disable_via_attr(double %x) #1 {
389; SSE-LABEL: trunc_signed_f64_disable_via_attr:
390; SSE:       # %bb.0:
391; SSE-NEXT:    cvttsd2si %xmm0, %rax
392; SSE-NEXT:    xorps %xmm0, %xmm0
393; SSE-NEXT:    cvtsi2sd %rax, %xmm0
394; SSE-NEXT:    retq
395;
396; AVX1-LABEL: trunc_signed_f64_disable_via_attr:
397; AVX1:       # %bb.0:
398; AVX1-NEXT:    vcvttsd2si %xmm0, %rax
399; AVX1-NEXT:    vcvtsi2sd %rax, %xmm1, %xmm0
400; AVX1-NEXT:    retq
401  %i = fptosi double %x to i64
402  %r = sitofp i64 %i to double
403  ret double %r
404}
405
406attributes #0 = { nounwind "no-signed-zeros-fp-math"="true" }
407attributes #1 = { nounwind "no-signed-zeros-fp-math"="true" "strict-float-cast-overflow"="false" }
408