xref: /llvm-project/llvm/test/CodeGen/X86/fpclamptosat.ll (revision a2a0089ac3a5781ba74d4d319c87c9e8b46d4eda)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
3
4; i32 saturate
5
6define i32 @stest_f64i32(double %x) nounwind {
7; CHECK-LABEL: stest_f64i32:
8; CHECK:       # %bb.0: # %entry
9; CHECK-NEXT:    xorl %eax, %eax
10; CHECK-NEXT:    ucomisd %xmm0, %xmm0
11; CHECK-NEXT:    maxsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
12; CHECK-NEXT:    minsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
13; CHECK-NEXT:    cvttsd2si %xmm0, %ecx
14; CHECK-NEXT:    cmovnpl %ecx, %eax
15; CHECK-NEXT:    retq
16entry:
17  %conv = fptosi double %x to i64
18  %0 = icmp slt i64 %conv, 2147483647
19  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
20  %1 = icmp sgt i64 %spec.store.select, -2147483648
21  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
22  %conv6 = trunc i64 %spec.store.select7 to i32
23  ret i32 %conv6
24}
25
26define i32 @utest_f64i32(double %x) nounwind {
27; CHECK-LABEL: utest_f64i32:
28; CHECK:       # %bb.0: # %entry
29; CHECK-NEXT:    cvttsd2si %xmm0, %rax
30; CHECK-NEXT:    movq %rax, %rcx
31; CHECK-NEXT:    sarq $63, %rcx
32; CHECK-NEXT:    subsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
33; CHECK-NEXT:    cvttsd2si %xmm0, %rdx
34; CHECK-NEXT:    andq %rcx, %rdx
35; CHECK-NEXT:    orq %rax, %rdx
36; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
37; CHECK-NEXT:    cmpq %rax, %rdx
38; CHECK-NEXT:    movl $-1, %eax
39; CHECK-NEXT:    cmovbl %edx, %eax
40; CHECK-NEXT:    retq
41entry:
42  %conv = fptoui double %x to i64
43  %0 = icmp ult i64 %conv, 4294967295
44  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
45  %conv6 = trunc i64 %spec.store.select to i32
46  ret i32 %conv6
47}
48
49define i32 @ustest_f64i32(double %x) nounwind {
50; CHECK-LABEL: ustest_f64i32:
51; CHECK:       # %bb.0: # %entry
52; CHECK-NEXT:    cvttsd2si %xmm0, %rcx
53; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
54; CHECK-NEXT:    cmpq %rax, %rcx
55; CHECK-NEXT:    cmovlq %rcx, %rax
56; CHECK-NEXT:    xorl %ecx, %ecx
57; CHECK-NEXT:    testq %rax, %rax
58; CHECK-NEXT:    cmovlel %ecx, %eax
59; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
60; CHECK-NEXT:    retq
61entry:
62  %conv = fptosi double %x to i64
63  %0 = icmp slt i64 %conv, 4294967295
64  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
65  %1 = icmp sgt i64 %spec.store.select, 0
66  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
67  %conv6 = trunc i64 %spec.store.select7 to i32
68  ret i32 %conv6
69}
70
71define i32 @stest_f32i32(float %x) nounwind {
72; CHECK-LABEL: stest_f32i32:
73; CHECK:       # %bb.0: # %entry
74; CHECK-NEXT:    cvttss2si %xmm0, %eax
75; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
76; CHECK-NEXT:    movl $2147483647, %ecx # imm = 0x7FFFFFFF
77; CHECK-NEXT:    cmovbel %eax, %ecx
78; CHECK-NEXT:    xorl %eax, %eax
79; CHECK-NEXT:    ucomiss %xmm0, %xmm0
80; CHECK-NEXT:    cmovnpl %ecx, %eax
81; CHECK-NEXT:    retq
82entry:
83  %conv = fptosi float %x to i64
84  %0 = icmp slt i64 %conv, 2147483647
85  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
86  %1 = icmp sgt i64 %spec.store.select, -2147483648
87  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
88  %conv6 = trunc i64 %spec.store.select7 to i32
89  ret i32 %conv6
90}
91
92define i32 @utest_f32i32(float %x) nounwind {
93; CHECK-LABEL: utest_f32i32:
94; CHECK:       # %bb.0: # %entry
95; CHECK-NEXT:    cvttss2si %xmm0, %rax
96; CHECK-NEXT:    movq %rax, %rcx
97; CHECK-NEXT:    sarq $63, %rcx
98; CHECK-NEXT:    subss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
99; CHECK-NEXT:    cvttss2si %xmm0, %rdx
100; CHECK-NEXT:    andq %rcx, %rdx
101; CHECK-NEXT:    orq %rax, %rdx
102; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
103; CHECK-NEXT:    cmpq %rax, %rdx
104; CHECK-NEXT:    movl $-1, %eax
105; CHECK-NEXT:    cmovbl %edx, %eax
106; CHECK-NEXT:    retq
107entry:
108  %conv = fptoui float %x to i64
109  %0 = icmp ult i64 %conv, 4294967295
110  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
111  %conv6 = trunc i64 %spec.store.select to i32
112  ret i32 %conv6
113}
114
115define i32 @ustest_f32i32(float %x) nounwind {
116; CHECK-LABEL: ustest_f32i32:
117; CHECK:       # %bb.0: # %entry
118; CHECK-NEXT:    cvttss2si %xmm0, %rcx
119; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
120; CHECK-NEXT:    cmpq %rax, %rcx
121; CHECK-NEXT:    cmovlq %rcx, %rax
122; CHECK-NEXT:    xorl %ecx, %ecx
123; CHECK-NEXT:    testq %rax, %rax
124; CHECK-NEXT:    cmovlel %ecx, %eax
125; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
126; CHECK-NEXT:    retq
127entry:
128  %conv = fptosi float %x to i64
129  %0 = icmp slt i64 %conv, 4294967295
130  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
131  %1 = icmp sgt i64 %spec.store.select, 0
132  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
133  %conv6 = trunc i64 %spec.store.select7 to i32
134  ret i32 %conv6
135}
136
137define i32 @stest_f16i32(half %x) nounwind {
138; CHECK-LABEL: stest_f16i32:
139; CHECK:       # %bb.0: # %entry
140; CHECK-NEXT:    pushq %rax
141; CHECK-NEXT:    callq __extendhfsf2@PLT
142; CHECK-NEXT:    cvttss2si %xmm0, %eax
143; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
144; CHECK-NEXT:    movl $-2147483648, %ecx # imm = 0x80000000
145; CHECK-NEXT:    cmovael %eax, %ecx
146; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
147; CHECK-NEXT:    movl $2147483647, %edx # imm = 0x7FFFFFFF
148; CHECK-NEXT:    cmovbel %ecx, %edx
149; CHECK-NEXT:    xorl %eax, %eax
150; CHECK-NEXT:    ucomiss %xmm0, %xmm0
151; CHECK-NEXT:    cmovnpl %edx, %eax
152; CHECK-NEXT:    popq %rcx
153; CHECK-NEXT:    retq
154entry:
155  %conv = fptosi half %x to i64
156  %0 = icmp slt i64 %conv, 2147483647
157  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
158  %1 = icmp sgt i64 %spec.store.select, -2147483648
159  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
160  %conv6 = trunc i64 %spec.store.select7 to i32
161  ret i32 %conv6
162}
163
164define i32 @utesth_f16i32(half %x) nounwind {
165; CHECK-LABEL: utesth_f16i32:
166; CHECK:       # %bb.0: # %entry
167; CHECK-NEXT:    pushq %rax
168; CHECK-NEXT:    callq __extendhfsf2@PLT
169; CHECK-NEXT:    cvttss2si %xmm0, %rax
170; CHECK-NEXT:    movq %rax, %rcx
171; CHECK-NEXT:    sarq $63, %rcx
172; CHECK-NEXT:    subss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
173; CHECK-NEXT:    cvttss2si %xmm0, %rdx
174; CHECK-NEXT:    andq %rcx, %rdx
175; CHECK-NEXT:    orq %rax, %rdx
176; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
177; CHECK-NEXT:    cmpq %rax, %rdx
178; CHECK-NEXT:    movl $-1, %eax
179; CHECK-NEXT:    cmovbl %edx, %eax
180; CHECK-NEXT:    popq %rcx
181; CHECK-NEXT:    retq
182entry:
183  %conv = fptoui half %x to i64
184  %0 = icmp ult i64 %conv, 4294967295
185  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
186  %conv6 = trunc i64 %spec.store.select to i32
187  ret i32 %conv6
188}
189
190define i32 @ustest_f16i32(half %x) nounwind {
191; CHECK-LABEL: ustest_f16i32:
192; CHECK:       # %bb.0: # %entry
193; CHECK-NEXT:    pushq %rax
194; CHECK-NEXT:    callq __extendhfsf2@PLT
195; CHECK-NEXT:    cvttss2si %xmm0, %rcx
196; CHECK-NEXT:    movl $4294967295, %eax # imm = 0xFFFFFFFF
197; CHECK-NEXT:    cmpq %rax, %rcx
198; CHECK-NEXT:    cmovlq %rcx, %rax
199; CHECK-NEXT:    xorl %ecx, %ecx
200; CHECK-NEXT:    testq %rax, %rax
201; CHECK-NEXT:    cmovlel %ecx, %eax
202; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
203; CHECK-NEXT:    popq %rcx
204; CHECK-NEXT:    retq
205entry:
206  %conv = fptosi half %x to i64
207  %0 = icmp slt i64 %conv, 4294967295
208  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
209  %1 = icmp sgt i64 %spec.store.select, 0
210  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
211  %conv6 = trunc i64 %spec.store.select7 to i32
212  ret i32 %conv6
213}
214
215; i16 saturate
216
217define i16 @stest_f64i16(double %x) nounwind {
218; CHECK-LABEL: stest_f64i16:
219; CHECK:       # %bb.0: # %entry
220; CHECK-NEXT:    movsd {{.*#+}} xmm1 = [-3.2768E+4,0.0E+0]
221; CHECK-NEXT:    maxsd %xmm0, %xmm1
222; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [3.2767E+4,0.0E+0]
223; CHECK-NEXT:    minsd %xmm1, %xmm0
224; CHECK-NEXT:    cvttsd2si %xmm0, %eax
225; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
226; CHECK-NEXT:    retq
227entry:
228  %conv = fptosi double %x to i32
229  %0 = icmp slt i32 %conv, 32767
230  %spec.store.select = select i1 %0, i32 %conv, i32 32767
231  %1 = icmp sgt i32 %spec.store.select, -32768
232  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
233  %conv6 = trunc i32 %spec.store.select7 to i16
234  ret i16 %conv6
235}
236
237define i16 @utest_f64i16(double %x) nounwind {
238; CHECK-LABEL: utest_f64i16:
239; CHECK:       # %bb.0: # %entry
240; CHECK-NEXT:    cvttsd2si %xmm0, %rcx
241; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
242; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
243; CHECK-NEXT:    cmovbl %ecx, %eax
244; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
245; CHECK-NEXT:    retq
246entry:
247  %conv = fptoui double %x to i32
248  %0 = icmp ult i32 %conv, 65535
249  %spec.store.select = select i1 %0, i32 %conv, i32 65535
250  %conv6 = trunc i32 %spec.store.select to i16
251  ret i16 %conv6
252}
253
254define i16 @ustest_f64i16(double %x) nounwind {
255; CHECK-LABEL: ustest_f64i16:
256; CHECK:       # %bb.0: # %entry
257; CHECK-NEXT:    cvttsd2si %xmm0, %eax
258; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
259; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
260; CHECK-NEXT:    cmovll %eax, %ecx
261; CHECK-NEXT:    xorl %eax, %eax
262; CHECK-NEXT:    testl %ecx, %ecx
263; CHECK-NEXT:    cmovgl %ecx, %eax
264; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
265; CHECK-NEXT:    retq
266entry:
267  %conv = fptosi double %x to i32
268  %0 = icmp slt i32 %conv, 65535
269  %spec.store.select = select i1 %0, i32 %conv, i32 65535
270  %1 = icmp sgt i32 %spec.store.select, 0
271  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
272  %conv6 = trunc i32 %spec.store.select7 to i16
273  ret i16 %conv6
274}
275
276define i16 @stest_f32i16(float %x) nounwind {
277; CHECK-LABEL: stest_f32i16:
278; CHECK:       # %bb.0: # %entry
279; CHECK-NEXT:    movss {{.*#+}} xmm1 = [-3.2768E+4,0.0E+0,0.0E+0,0.0E+0]
280; CHECK-NEXT:    maxss %xmm0, %xmm1
281; CHECK-NEXT:    movss {{.*#+}} xmm0 = [3.2767E+4,0.0E+0,0.0E+0,0.0E+0]
282; CHECK-NEXT:    minss %xmm1, %xmm0
283; CHECK-NEXT:    cvttss2si %xmm0, %eax
284; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
285; CHECK-NEXT:    retq
286entry:
287  %conv = fptosi float %x to i32
288  %0 = icmp slt i32 %conv, 32767
289  %spec.store.select = select i1 %0, i32 %conv, i32 32767
290  %1 = icmp sgt i32 %spec.store.select, -32768
291  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
292  %conv6 = trunc i32 %spec.store.select7 to i16
293  ret i16 %conv6
294}
295
296define i16 @utest_f32i16(float %x) nounwind {
297; CHECK-LABEL: utest_f32i16:
298; CHECK:       # %bb.0: # %entry
299; CHECK-NEXT:    cvttss2si %xmm0, %rcx
300; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
301; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
302; CHECK-NEXT:    cmovbl %ecx, %eax
303; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
304; CHECK-NEXT:    retq
305entry:
306  %conv = fptoui float %x to i32
307  %0 = icmp ult i32 %conv, 65535
308  %spec.store.select = select i1 %0, i32 %conv, i32 65535
309  %conv6 = trunc i32 %spec.store.select to i16
310  ret i16 %conv6
311}
312
313define i16 @ustest_f32i16(float %x) nounwind {
314; CHECK-LABEL: ustest_f32i16:
315; CHECK:       # %bb.0: # %entry
316; CHECK-NEXT:    cvttss2si %xmm0, %eax
317; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
318; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
319; CHECK-NEXT:    cmovll %eax, %ecx
320; CHECK-NEXT:    xorl %eax, %eax
321; CHECK-NEXT:    testl %ecx, %ecx
322; CHECK-NEXT:    cmovgl %ecx, %eax
323; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
324; CHECK-NEXT:    retq
325entry:
326  %conv = fptosi float %x to i32
327  %0 = icmp slt i32 %conv, 65535
328  %spec.store.select = select i1 %0, i32 %conv, i32 65535
329  %1 = icmp sgt i32 %spec.store.select, 0
330  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
331  %conv6 = trunc i32 %spec.store.select7 to i16
332  ret i16 %conv6
333}
334
335define i16 @stest_f16i16(half %x) nounwind {
336; CHECK-LABEL: stest_f16i16:
337; CHECK:       # %bb.0: # %entry
338; CHECK-NEXT:    pushq %rax
339; CHECK-NEXT:    callq __extendhfsf2@PLT
340; CHECK-NEXT:    cvttss2si %xmm0, %eax
341; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
342; CHECK-NEXT:    movl $32768, %ecx # imm = 0x8000
343; CHECK-NEXT:    cmovael %eax, %ecx
344; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
345; CHECK-NEXT:    movl $32767, %edx # imm = 0x7FFF
346; CHECK-NEXT:    cmovbel %ecx, %edx
347; CHECK-NEXT:    xorl %eax, %eax
348; CHECK-NEXT:    ucomiss %xmm0, %xmm0
349; CHECK-NEXT:    cmovnpl %edx, %eax
350; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
351; CHECK-NEXT:    popq %rcx
352; CHECK-NEXT:    retq
353entry:
354  %conv = fptosi half %x to i32
355  %0 = icmp slt i32 %conv, 32767
356  %spec.store.select = select i1 %0, i32 %conv, i32 32767
357  %1 = icmp sgt i32 %spec.store.select, -32768
358  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
359  %conv6 = trunc i32 %spec.store.select7 to i16
360  ret i16 %conv6
361}
362
363define i16 @utesth_f16i16(half %x) nounwind {
364; CHECK-LABEL: utesth_f16i16:
365; CHECK:       # %bb.0: # %entry
366; CHECK-NEXT:    pushq %rax
367; CHECK-NEXT:    callq __extendhfsf2@PLT
368; CHECK-NEXT:    cvttss2si %xmm0, %rcx
369; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
370; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
371; CHECK-NEXT:    cmovbl %ecx, %eax
372; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
373; CHECK-NEXT:    popq %rcx
374; CHECK-NEXT:    retq
375entry:
376  %conv = fptoui half %x to i32
377  %0 = icmp ult i32 %conv, 65535
378  %spec.store.select = select i1 %0, i32 %conv, i32 65535
379  %conv6 = trunc i32 %spec.store.select to i16
380  ret i16 %conv6
381}
382
383define i16 @ustest_f16i16(half %x) nounwind {
384; CHECK-LABEL: ustest_f16i16:
385; CHECK:       # %bb.0: # %entry
386; CHECK-NEXT:    pushq %rax
387; CHECK-NEXT:    callq __extendhfsf2@PLT
388; CHECK-NEXT:    cvttss2si %xmm0, %eax
389; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
390; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
391; CHECK-NEXT:    cmovll %eax, %ecx
392; CHECK-NEXT:    xorl %eax, %eax
393; CHECK-NEXT:    testl %ecx, %ecx
394; CHECK-NEXT:    cmovgl %ecx, %eax
395; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
396; CHECK-NEXT:    popq %rcx
397; CHECK-NEXT:    retq
398entry:
399  %conv = fptosi half %x to i32
400  %0 = icmp slt i32 %conv, 65535
401  %spec.store.select = select i1 %0, i32 %conv, i32 65535
402  %1 = icmp sgt i32 %spec.store.select, 0
403  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
404  %conv6 = trunc i32 %spec.store.select7 to i16
405  ret i16 %conv6
406}
407
408; i64 saturate
409
410define i64 @stest_f64i64(double %x) nounwind {
411; CHECK-LABEL: stest_f64i64:
412; CHECK:       # %bb.0: # %entry
413; CHECK-NEXT:    cvttsd2si %xmm0, %rax
414; CHECK-NEXT:    ucomisd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
415; CHECK-NEXT:    movabsq $9223372036854775807, %rcx # imm = 0x7FFFFFFFFFFFFFFF
416; CHECK-NEXT:    cmovbeq %rax, %rcx
417; CHECK-NEXT:    xorl %eax, %eax
418; CHECK-NEXT:    ucomisd %xmm0, %xmm0
419; CHECK-NEXT:    cmovnpq %rcx, %rax
420; CHECK-NEXT:    retq
421entry:
422  %conv = fptosi double %x to i128
423  %0 = icmp slt i128 %conv, 9223372036854775807
424  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
425  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
426  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
427  %conv6 = trunc i128 %spec.store.select7 to i64
428  ret i64 %conv6
429}
430
431define i64 @utest_f64i64(double %x) nounwind {
432; CHECK-LABEL: utest_f64i64:
433; CHECK:       # %bb.0: # %entry
434; CHECK-NEXT:    pushq %rax
435; CHECK-NEXT:    callq __fixunsdfti@PLT
436; CHECK-NEXT:    xorl %ecx, %ecx
437; CHECK-NEXT:    testq %rdx, %rdx
438; CHECK-NEXT:    cmovneq %rcx, %rax
439; CHECK-NEXT:    popq %rcx
440; CHECK-NEXT:    retq
441entry:
442  %conv = fptoui double %x to i128
443  %0 = icmp ult i128 %conv, 18446744073709551616
444  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
445  %conv6 = trunc i128 %spec.store.select to i64
446  ret i64 %conv6
447}
448
449define i64 @ustest_f64i64(double %x) nounwind {
450; CHECK-LABEL: ustest_f64i64:
451; CHECK:       # %bb.0: # %entry
452; CHECK-NEXT:    pushq %rax
453; CHECK-NEXT:    callq __fixdfti@PLT
454; CHECK-NEXT:    xorl %ecx, %ecx
455; CHECK-NEXT:    testq %rdx, %rdx
456; CHECK-NEXT:    movl $1, %esi
457; CHECK-NEXT:    cmovleq %rdx, %rsi
458; CHECK-NEXT:    cmovgq %rcx, %rax
459; CHECK-NEXT:    movq %rax, %rdx
460; CHECK-NEXT:    negq %rdx
461; CHECK-NEXT:    movl $0, %edx
462; CHECK-NEXT:    sbbq %rsi, %rdx
463; CHECK-NEXT:    cmovgeq %rcx, %rax
464; CHECK-NEXT:    popq %rcx
465; CHECK-NEXT:    retq
466entry:
467  %conv = fptosi double %x to i128
468  %0 = icmp slt i128 %conv, 18446744073709551616
469  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
470  %1 = icmp sgt i128 %spec.store.select, 0
471  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
472  %conv6 = trunc i128 %spec.store.select7 to i64
473  ret i64 %conv6
474}
475
476define i64 @stest_f32i64(float %x) nounwind {
477; CHECK-LABEL: stest_f32i64:
478; CHECK:       # %bb.0: # %entry
479; CHECK-NEXT:    cvttss2si %xmm0, %rax
480; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
481; CHECK-NEXT:    movabsq $9223372036854775807, %rcx # imm = 0x7FFFFFFFFFFFFFFF
482; CHECK-NEXT:    cmovbeq %rax, %rcx
483; CHECK-NEXT:    xorl %eax, %eax
484; CHECK-NEXT:    ucomiss %xmm0, %xmm0
485; CHECK-NEXT:    cmovnpq %rcx, %rax
486; CHECK-NEXT:    retq
487entry:
488  %conv = fptosi float %x to i128
489  %0 = icmp slt i128 %conv, 9223372036854775807
490  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
491  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
492  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
493  %conv6 = trunc i128 %spec.store.select7 to i64
494  ret i64 %conv6
495}
496
497define i64 @utest_f32i64(float %x) nounwind {
498; CHECK-LABEL: utest_f32i64:
499; CHECK:       # %bb.0: # %entry
500; CHECK-NEXT:    pushq %rax
501; CHECK-NEXT:    callq __fixunssfti@PLT
502; CHECK-NEXT:    xorl %ecx, %ecx
503; CHECK-NEXT:    testq %rdx, %rdx
504; CHECK-NEXT:    cmovneq %rcx, %rax
505; CHECK-NEXT:    popq %rcx
506; CHECK-NEXT:    retq
507entry:
508  %conv = fptoui float %x to i128
509  %0 = icmp ult i128 %conv, 18446744073709551616
510  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
511  %conv6 = trunc i128 %spec.store.select to i64
512  ret i64 %conv6
513}
514
515define i64 @ustest_f32i64(float %x) nounwind {
516; CHECK-LABEL: ustest_f32i64:
517; CHECK:       # %bb.0: # %entry
518; CHECK-NEXT:    pushq %rax
519; CHECK-NEXT:    callq __fixsfti@PLT
520; CHECK-NEXT:    xorl %ecx, %ecx
521; CHECK-NEXT:    testq %rdx, %rdx
522; CHECK-NEXT:    movl $1, %esi
523; CHECK-NEXT:    cmovleq %rdx, %rsi
524; CHECK-NEXT:    cmovgq %rcx, %rax
525; CHECK-NEXT:    movq %rax, %rdx
526; CHECK-NEXT:    negq %rdx
527; CHECK-NEXT:    movl $0, %edx
528; CHECK-NEXT:    sbbq %rsi, %rdx
529; CHECK-NEXT:    cmovgeq %rcx, %rax
530; CHECK-NEXT:    popq %rcx
531; CHECK-NEXT:    retq
532entry:
533  %conv = fptosi float %x to i128
534  %0 = icmp slt i128 %conv, 18446744073709551616
535  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
536  %1 = icmp sgt i128 %spec.store.select, 0
537  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
538  %conv6 = trunc i128 %spec.store.select7 to i64
539  ret i64 %conv6
540}
541
542define i64 @stest_f16i64(half %x) nounwind {
543; CHECK-LABEL: stest_f16i64:
544; CHECK:       # %bb.0: # %entry
545; CHECK-NEXT:    pushq %rax
546; CHECK-NEXT:    callq __extendhfsf2@PLT
547; CHECK-NEXT:    cvttss2si %xmm0, %rax
548; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
549; CHECK-NEXT:    movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
550; CHECK-NEXT:    cmovaeq %rax, %rcx
551; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
552; CHECK-NEXT:    movabsq $9223372036854775807, %rdx # imm = 0x7FFFFFFFFFFFFFFF
553; CHECK-NEXT:    cmovbeq %rcx, %rdx
554; CHECK-NEXT:    xorl %eax, %eax
555; CHECK-NEXT:    ucomiss %xmm0, %xmm0
556; CHECK-NEXT:    cmovnpq %rdx, %rax
557; CHECK-NEXT:    popq %rcx
558; CHECK-NEXT:    retq
559entry:
560  %conv = fptosi half %x to i128
561  %0 = icmp slt i128 %conv, 9223372036854775807
562  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
563  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
564  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
565  %conv6 = trunc i128 %spec.store.select7 to i64
566  ret i64 %conv6
567}
568
569define i64 @utesth_f16i64(half %x) nounwind {
570; CHECK-LABEL: utesth_f16i64:
571; CHECK:       # %bb.0: # %entry
572; CHECK-NEXT:    pushq %rax
573; CHECK-NEXT:    callq __fixunshfti@PLT
574; CHECK-NEXT:    xorl %ecx, %ecx
575; CHECK-NEXT:    testq %rdx, %rdx
576; CHECK-NEXT:    cmovneq %rcx, %rax
577; CHECK-NEXT:    popq %rcx
578; CHECK-NEXT:    retq
579entry:
580  %conv = fptoui half %x to i128
581  %0 = icmp ult i128 %conv, 18446744073709551616
582  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
583  %conv6 = trunc i128 %spec.store.select to i64
584  ret i64 %conv6
585}
586
587define i64 @ustest_f16i64(half %x) nounwind {
588; CHECK-LABEL: ustest_f16i64:
589; CHECK:       # %bb.0: # %entry
590; CHECK-NEXT:    pushq %rax
591; CHECK-NEXT:    callq __fixhfti@PLT
592; CHECK-NEXT:    xorl %ecx, %ecx
593; CHECK-NEXT:    testq %rdx, %rdx
594; CHECK-NEXT:    movl $1, %esi
595; CHECK-NEXT:    cmovleq %rdx, %rsi
596; CHECK-NEXT:    cmovgq %rcx, %rax
597; CHECK-NEXT:    movq %rax, %rdx
598; CHECK-NEXT:    negq %rdx
599; CHECK-NEXT:    movl $0, %edx
600; CHECK-NEXT:    sbbq %rsi, %rdx
601; CHECK-NEXT:    cmovgeq %rcx, %rax
602; CHECK-NEXT:    popq %rcx
603; CHECK-NEXT:    retq
604entry:
605  %conv = fptosi half %x to i128
606  %0 = icmp slt i128 %conv, 18446744073709551616
607  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
608  %1 = icmp sgt i128 %spec.store.select, 0
609  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
610  %conv6 = trunc i128 %spec.store.select7 to i64
611  ret i64 %conv6
612}
613
614
615
616
617; i32 saturate
618
619define i32 @stest_f64i32_mm(double %x) nounwind {
620; CHECK-LABEL: stest_f64i32_mm:
621; CHECK:       # %bb.0: # %entry
622; CHECK-NEXT:    xorl %eax, %eax
623; CHECK-NEXT:    ucomisd %xmm0, %xmm0
624; CHECK-NEXT:    maxsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
625; CHECK-NEXT:    minsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
626; CHECK-NEXT:    cvttsd2si %xmm0, %ecx
627; CHECK-NEXT:    cmovnpl %ecx, %eax
628; CHECK-NEXT:    retq
629entry:
630  %conv = fptosi double %x to i64
631  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
632  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
633  %conv6 = trunc i64 %spec.store.select7 to i32
634  ret i32 %conv6
635}
636
637define i32 @utest_f64i32_mm(double %x) nounwind {
638; CHECK-LABEL: utest_f64i32_mm:
639; CHECK:       # %bb.0: # %entry
640; CHECK-NEXT:    cvttsd2si %xmm0, %rcx
641; CHECK-NEXT:    movq %rcx, %rdx
642; CHECK-NEXT:    sarq $63, %rdx
643; CHECK-NEXT:    subsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
644; CHECK-NEXT:    cvttsd2si %xmm0, %rax
645; CHECK-NEXT:    andq %rdx, %rax
646; CHECK-NEXT:    orq %rcx, %rax
647; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
648; CHECK-NEXT:    cmpq %rcx, %rax
649; CHECK-NEXT:    cmovaeq %rcx, %rax
650; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
651; CHECK-NEXT:    retq
652entry:
653  %conv = fptoui double %x to i64
654  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
655  %conv6 = trunc i64 %spec.store.select to i32
656  ret i32 %conv6
657}
658
659define i32 @ustest_f64i32_mm(double %x) nounwind {
660; CHECK-LABEL: ustest_f64i32_mm:
661; CHECK:       # %bb.0: # %entry
662; CHECK-NEXT:    cvttsd2si %xmm0, %rax
663; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
664; CHECK-NEXT:    cmpq %rcx, %rax
665; CHECK-NEXT:    cmovlq %rax, %rcx
666; CHECK-NEXT:    xorl %eax, %eax
667; CHECK-NEXT:    testq %rcx, %rcx
668; CHECK-NEXT:    cmovgq %rcx, %rax
669; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
670; CHECK-NEXT:    retq
671entry:
672  %conv = fptosi double %x to i64
673  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
674  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
675  %conv6 = trunc i64 %spec.store.select7 to i32
676  ret i32 %conv6
677}
678
679define i32 @stest_f32i32_mm(float %x) nounwind {
680; CHECK-LABEL: stest_f32i32_mm:
681; CHECK:       # %bb.0: # %entry
682; CHECK-NEXT:    cvttss2si %xmm0, %eax
683; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
684; CHECK-NEXT:    movl $2147483647, %ecx # imm = 0x7FFFFFFF
685; CHECK-NEXT:    cmovbel %eax, %ecx
686; CHECK-NEXT:    xorl %eax, %eax
687; CHECK-NEXT:    ucomiss %xmm0, %xmm0
688; CHECK-NEXT:    cmovnpl %ecx, %eax
689; CHECK-NEXT:    retq
690entry:
691  %conv = fptosi float %x to i64
692  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
693  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
694  %conv6 = trunc i64 %spec.store.select7 to i32
695  ret i32 %conv6
696}
697
698define i32 @utest_f32i32_mm(float %x) nounwind {
699; CHECK-LABEL: utest_f32i32_mm:
700; CHECK:       # %bb.0: # %entry
701; CHECK-NEXT:    cvttss2si %xmm0, %rcx
702; CHECK-NEXT:    movq %rcx, %rdx
703; CHECK-NEXT:    sarq $63, %rdx
704; CHECK-NEXT:    subss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
705; CHECK-NEXT:    cvttss2si %xmm0, %rax
706; CHECK-NEXT:    andq %rdx, %rax
707; CHECK-NEXT:    orq %rcx, %rax
708; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
709; CHECK-NEXT:    cmpq %rcx, %rax
710; CHECK-NEXT:    cmovaeq %rcx, %rax
711; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
712; CHECK-NEXT:    retq
713entry:
714  %conv = fptoui float %x to i64
715  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
716  %conv6 = trunc i64 %spec.store.select to i32
717  ret i32 %conv6
718}
719
720define i32 @ustest_f32i32_mm(float %x) nounwind {
721; CHECK-LABEL: ustest_f32i32_mm:
722; CHECK:       # %bb.0: # %entry
723; CHECK-NEXT:    cvttss2si %xmm0, %rax
724; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
725; CHECK-NEXT:    cmpq %rcx, %rax
726; CHECK-NEXT:    cmovlq %rax, %rcx
727; CHECK-NEXT:    xorl %eax, %eax
728; CHECK-NEXT:    testq %rcx, %rcx
729; CHECK-NEXT:    cmovgq %rcx, %rax
730; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
731; CHECK-NEXT:    retq
732entry:
733  %conv = fptosi float %x to i64
734  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
735  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
736  %conv6 = trunc i64 %spec.store.select7 to i32
737  ret i32 %conv6
738}
739
740define i32 @stest_f16i32_mm(half %x) nounwind {
741; CHECK-LABEL: stest_f16i32_mm:
742; CHECK:       # %bb.0: # %entry
743; CHECK-NEXT:    pushq %rax
744; CHECK-NEXT:    callq __extendhfsf2@PLT
745; CHECK-NEXT:    cvttss2si %xmm0, %eax
746; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
747; CHECK-NEXT:    movl $-2147483648, %ecx # imm = 0x80000000
748; CHECK-NEXT:    cmovael %eax, %ecx
749; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
750; CHECK-NEXT:    movl $2147483647, %edx # imm = 0x7FFFFFFF
751; CHECK-NEXT:    cmovbel %ecx, %edx
752; CHECK-NEXT:    xorl %eax, %eax
753; CHECK-NEXT:    ucomiss %xmm0, %xmm0
754; CHECK-NEXT:    cmovnpl %edx, %eax
755; CHECK-NEXT:    popq %rcx
756; CHECK-NEXT:    retq
757entry:
758  %conv = fptosi half %x to i64
759  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
760  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
761  %conv6 = trunc i64 %spec.store.select7 to i32
762  ret i32 %conv6
763}
764
765define i32 @utesth_f16i32_mm(half %x) nounwind {
766; CHECK-LABEL: utesth_f16i32_mm:
767; CHECK:       # %bb.0: # %entry
768; CHECK-NEXT:    pushq %rax
769; CHECK-NEXT:    callq __extendhfsf2@PLT
770; CHECK-NEXT:    cvttss2si %xmm0, %rcx
771; CHECK-NEXT:    movq %rcx, %rdx
772; CHECK-NEXT:    sarq $63, %rdx
773; CHECK-NEXT:    subss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
774; CHECK-NEXT:    cvttss2si %xmm0, %rax
775; CHECK-NEXT:    andq %rdx, %rax
776; CHECK-NEXT:    orq %rcx, %rax
777; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
778; CHECK-NEXT:    cmpq %rcx, %rax
779; CHECK-NEXT:    cmovaeq %rcx, %rax
780; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
781; CHECK-NEXT:    popq %rcx
782; CHECK-NEXT:    retq
783entry:
784  %conv = fptoui half %x to i64
785  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
786  %conv6 = trunc i64 %spec.store.select to i32
787  ret i32 %conv6
788}
789
790define i32 @ustest_f16i32_mm(half %x) nounwind {
791; CHECK-LABEL: ustest_f16i32_mm:
792; CHECK:       # %bb.0: # %entry
793; CHECK-NEXT:    pushq %rax
794; CHECK-NEXT:    callq __extendhfsf2@PLT
795; CHECK-NEXT:    cvttss2si %xmm0, %rax
796; CHECK-NEXT:    movl $4294967295, %ecx # imm = 0xFFFFFFFF
797; CHECK-NEXT:    cmpq %rcx, %rax
798; CHECK-NEXT:    cmovlq %rax, %rcx
799; CHECK-NEXT:    xorl %eax, %eax
800; CHECK-NEXT:    testq %rcx, %rcx
801; CHECK-NEXT:    cmovgq %rcx, %rax
802; CHECK-NEXT:    # kill: def $eax killed $eax killed $rax
803; CHECK-NEXT:    popq %rcx
804; CHECK-NEXT:    retq
805entry:
806  %conv = fptosi half %x to i64
807  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
808  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
809  %conv6 = trunc i64 %spec.store.select7 to i32
810  ret i32 %conv6
811}
812
813; i16 saturate
814
815define i16 @stest_f64i16_mm(double %x) nounwind {
816; CHECK-LABEL: stest_f64i16_mm:
817; CHECK:       # %bb.0: # %entry
818; CHECK-NEXT:    movsd {{.*#+}} xmm1 = [-3.2768E+4,0.0E+0]
819; CHECK-NEXT:    maxsd %xmm0, %xmm1
820; CHECK-NEXT:    movsd {{.*#+}} xmm0 = [3.2767E+4,0.0E+0]
821; CHECK-NEXT:    minsd %xmm1, %xmm0
822; CHECK-NEXT:    cvttsd2si %xmm0, %eax
823; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
824; CHECK-NEXT:    retq
825entry:
826  %conv = fptosi double %x to i32
827  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
828  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
829  %conv6 = trunc i32 %spec.store.select7 to i16
830  ret i16 %conv6
831}
832
833define i16 @utest_f64i16_mm(double %x) nounwind {
834; CHECK-LABEL: utest_f64i16_mm:
835; CHECK:       # %bb.0: # %entry
836; CHECK-NEXT:    cvttsd2si %xmm0, %rcx
837; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
838; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
839; CHECK-NEXT:    cmovbl %ecx, %eax
840; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
841; CHECK-NEXT:    retq
842entry:
843  %conv = fptoui double %x to i32
844  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
845  %conv6 = trunc i32 %spec.store.select to i16
846  ret i16 %conv6
847}
848
849define i16 @ustest_f64i16_mm(double %x) nounwind {
850; CHECK-LABEL: ustest_f64i16_mm:
851; CHECK:       # %bb.0: # %entry
852; CHECK-NEXT:    cvttsd2si %xmm0, %eax
853; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
854; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
855; CHECK-NEXT:    cmovll %eax, %ecx
856; CHECK-NEXT:    xorl %eax, %eax
857; CHECK-NEXT:    testl %ecx, %ecx
858; CHECK-NEXT:    cmovgl %ecx, %eax
859; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
860; CHECK-NEXT:    retq
861entry:
862  %conv = fptosi double %x to i32
863  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
864  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
865  %conv6 = trunc i32 %spec.store.select7 to i16
866  ret i16 %conv6
867}
868
869define i16 @stest_f32i16_mm(float %x) nounwind {
870; CHECK-LABEL: stest_f32i16_mm:
871; CHECK:       # %bb.0: # %entry
872; CHECK-NEXT:    movss {{.*#+}} xmm1 = [-3.2768E+4,0.0E+0,0.0E+0,0.0E+0]
873; CHECK-NEXT:    maxss %xmm0, %xmm1
874; CHECK-NEXT:    movss {{.*#+}} xmm0 = [3.2767E+4,0.0E+0,0.0E+0,0.0E+0]
875; CHECK-NEXT:    minss %xmm1, %xmm0
876; CHECK-NEXT:    cvttss2si %xmm0, %eax
877; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
878; CHECK-NEXT:    retq
879entry:
880  %conv = fptosi float %x to i32
881  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
882  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
883  %conv6 = trunc i32 %spec.store.select7 to i16
884  ret i16 %conv6
885}
886
887define i16 @utest_f32i16_mm(float %x) nounwind {
888; CHECK-LABEL: utest_f32i16_mm:
889; CHECK:       # %bb.0: # %entry
890; CHECK-NEXT:    cvttss2si %xmm0, %rcx
891; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
892; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
893; CHECK-NEXT:    cmovbl %ecx, %eax
894; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
895; CHECK-NEXT:    retq
896entry:
897  %conv = fptoui float %x to i32
898  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
899  %conv6 = trunc i32 %spec.store.select to i16
900  ret i16 %conv6
901}
902
903define i16 @ustest_f32i16_mm(float %x) nounwind {
904; CHECK-LABEL: ustest_f32i16_mm:
905; CHECK:       # %bb.0: # %entry
906; CHECK-NEXT:    cvttss2si %xmm0, %eax
907; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
908; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
909; CHECK-NEXT:    cmovll %eax, %ecx
910; CHECK-NEXT:    xorl %eax, %eax
911; CHECK-NEXT:    testl %ecx, %ecx
912; CHECK-NEXT:    cmovgl %ecx, %eax
913; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
914; CHECK-NEXT:    retq
915entry:
916  %conv = fptosi float %x to i32
917  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
918  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
919  %conv6 = trunc i32 %spec.store.select7 to i16
920  ret i16 %conv6
921}
922
923define i16 @stest_f16i16_mm(half %x) nounwind {
924; CHECK-LABEL: stest_f16i16_mm:
925; CHECK:       # %bb.0: # %entry
926; CHECK-NEXT:    pushq %rax
927; CHECK-NEXT:    callq __extendhfsf2@PLT
928; CHECK-NEXT:    cvttss2si %xmm0, %eax
929; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
930; CHECK-NEXT:    movl $32768, %ecx # imm = 0x8000
931; CHECK-NEXT:    cmovael %eax, %ecx
932; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
933; CHECK-NEXT:    movl $32767, %edx # imm = 0x7FFF
934; CHECK-NEXT:    cmovbel %ecx, %edx
935; CHECK-NEXT:    xorl %eax, %eax
936; CHECK-NEXT:    ucomiss %xmm0, %xmm0
937; CHECK-NEXT:    cmovnpl %edx, %eax
938; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
939; CHECK-NEXT:    popq %rcx
940; CHECK-NEXT:    retq
941entry:
942  %conv = fptosi half %x to i32
943  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
944  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
945  %conv6 = trunc i32 %spec.store.select7 to i16
946  ret i16 %conv6
947}
948
949define i16 @utesth_f16i16_mm(half %x) nounwind {
950; CHECK-LABEL: utesth_f16i16_mm:
951; CHECK:       # %bb.0: # %entry
952; CHECK-NEXT:    pushq %rax
953; CHECK-NEXT:    callq __extendhfsf2@PLT
954; CHECK-NEXT:    cvttss2si %xmm0, %rcx
955; CHECK-NEXT:    cmpl $65535, %ecx # imm = 0xFFFF
956; CHECK-NEXT:    movl $65535, %eax # imm = 0xFFFF
957; CHECK-NEXT:    cmovbl %ecx, %eax
958; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
959; CHECK-NEXT:    popq %rcx
960; CHECK-NEXT:    retq
961entry:
962  %conv = fptoui half %x to i32
963  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
964  %conv6 = trunc i32 %spec.store.select to i16
965  ret i16 %conv6
966}
967
968define i16 @ustest_f16i16_mm(half %x) nounwind {
969; CHECK-LABEL: ustest_f16i16_mm:
970; CHECK:       # %bb.0: # %entry
971; CHECK-NEXT:    pushq %rax
972; CHECK-NEXT:    callq __extendhfsf2@PLT
973; CHECK-NEXT:    cvttss2si %xmm0, %eax
974; CHECK-NEXT:    cmpl $65535, %eax # imm = 0xFFFF
975; CHECK-NEXT:    movl $65535, %ecx # imm = 0xFFFF
976; CHECK-NEXT:    cmovll %eax, %ecx
977; CHECK-NEXT:    xorl %eax, %eax
978; CHECK-NEXT:    testl %ecx, %ecx
979; CHECK-NEXT:    cmovgl %ecx, %eax
980; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
981; CHECK-NEXT:    popq %rcx
982; CHECK-NEXT:    retq
983entry:
984  %conv = fptosi half %x to i32
985  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
986  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
987  %conv6 = trunc i32 %spec.store.select7 to i16
988  ret i16 %conv6
989}
990
991; i64 saturate
992
993define i64 @stest_f64i64_mm(double %x) nounwind {
994; CHECK-LABEL: stest_f64i64_mm:
995; CHECK:       # %bb.0: # %entry
996; CHECK-NEXT:    cvttsd2si %xmm0, %rax
997; CHECK-NEXT:    ucomisd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
998; CHECK-NEXT:    movabsq $9223372036854775807, %rcx # imm = 0x7FFFFFFFFFFFFFFF
999; CHECK-NEXT:    cmovbeq %rax, %rcx
1000; CHECK-NEXT:    xorl %eax, %eax
1001; CHECK-NEXT:    ucomisd %xmm0, %xmm0
1002; CHECK-NEXT:    cmovnpq %rcx, %rax
1003; CHECK-NEXT:    retq
1004entry:
1005  %conv = fptosi double %x to i128
1006  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1007  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1008  %conv6 = trunc i128 %spec.store.select7 to i64
1009  ret i64 %conv6
1010}
1011
1012define i64 @utest_f64i64_mm(double %x) nounwind {
1013; CHECK-LABEL: utest_f64i64_mm:
1014; CHECK:       # %bb.0: # %entry
1015; CHECK-NEXT:    pushq %rax
1016; CHECK-NEXT:    callq __fixunsdfti@PLT
1017; CHECK-NEXT:    xorl %ecx, %ecx
1018; CHECK-NEXT:    testq %rdx, %rdx
1019; CHECK-NEXT:    cmovneq %rcx, %rax
1020; CHECK-NEXT:    popq %rcx
1021; CHECK-NEXT:    retq
1022entry:
1023  %conv = fptoui double %x to i128
1024  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1025  %conv6 = trunc i128 %spec.store.select to i64
1026  ret i64 %conv6
1027}
1028
1029define i64 @ustest_f64i64_mm(double %x) nounwind {
1030; CHECK-LABEL: ustest_f64i64_mm:
1031; CHECK:       # %bb.0: # %entry
1032; CHECK-NEXT:    pushq %rax
1033; CHECK-NEXT:    callq __fixdfti@PLT
1034; CHECK-NEXT:    xorl %ecx, %ecx
1035; CHECK-NEXT:    testq %rdx, %rdx
1036; CHECK-NEXT:    cmovgq %rcx, %rax
1037; CHECK-NEXT:    movl $1, %esi
1038; CHECK-NEXT:    cmovleq %rdx, %rsi
1039; CHECK-NEXT:    testq %rsi, %rsi
1040; CHECK-NEXT:    cmovsq %rcx, %rax
1041; CHECK-NEXT:    popq %rcx
1042; CHECK-NEXT:    retq
1043entry:
1044  %conv = fptosi double %x to i128
1045  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1046  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1047  %conv6 = trunc i128 %spec.store.select7 to i64
1048  ret i64 %conv6
1049}
1050
1051define i64 @stest_f32i64_mm(float %x) nounwind {
1052; CHECK-LABEL: stest_f32i64_mm:
1053; CHECK:       # %bb.0: # %entry
1054; CHECK-NEXT:    cvttss2si %xmm0, %rax
1055; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
1056; CHECK-NEXT:    movabsq $9223372036854775807, %rcx # imm = 0x7FFFFFFFFFFFFFFF
1057; CHECK-NEXT:    cmovbeq %rax, %rcx
1058; CHECK-NEXT:    xorl %eax, %eax
1059; CHECK-NEXT:    ucomiss %xmm0, %xmm0
1060; CHECK-NEXT:    cmovnpq %rcx, %rax
1061; CHECK-NEXT:    retq
1062entry:
1063  %conv = fptosi float %x to i128
1064  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1065  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1066  %conv6 = trunc i128 %spec.store.select7 to i64
1067  ret i64 %conv6
1068}
1069
1070define i64 @utest_f32i64_mm(float %x) nounwind {
1071; CHECK-LABEL: utest_f32i64_mm:
1072; CHECK:       # %bb.0: # %entry
1073; CHECK-NEXT:    pushq %rax
1074; CHECK-NEXT:    callq __fixunssfti@PLT
1075; CHECK-NEXT:    xorl %ecx, %ecx
1076; CHECK-NEXT:    testq %rdx, %rdx
1077; CHECK-NEXT:    cmovneq %rcx, %rax
1078; CHECK-NEXT:    popq %rcx
1079; CHECK-NEXT:    retq
1080entry:
1081  %conv = fptoui float %x to i128
1082  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1083  %conv6 = trunc i128 %spec.store.select to i64
1084  ret i64 %conv6
1085}
1086
1087define i64 @ustest_f32i64_mm(float %x) nounwind {
1088; CHECK-LABEL: ustest_f32i64_mm:
1089; CHECK:       # %bb.0: # %entry
1090; CHECK-NEXT:    pushq %rax
1091; CHECK-NEXT:    callq __fixsfti@PLT
1092; CHECK-NEXT:    xorl %ecx, %ecx
1093; CHECK-NEXT:    testq %rdx, %rdx
1094; CHECK-NEXT:    cmovgq %rcx, %rax
1095; CHECK-NEXT:    movl $1, %esi
1096; CHECK-NEXT:    cmovleq %rdx, %rsi
1097; CHECK-NEXT:    testq %rsi, %rsi
1098; CHECK-NEXT:    cmovsq %rcx, %rax
1099; CHECK-NEXT:    popq %rcx
1100; CHECK-NEXT:    retq
1101entry:
1102  %conv = fptosi float %x to i128
1103  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1104  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1105  %conv6 = trunc i128 %spec.store.select7 to i64
1106  ret i64 %conv6
1107}
1108
1109define i64 @stest_f16i64_mm(half %x) nounwind {
1110; CHECK-LABEL: stest_f16i64_mm:
1111; CHECK:       # %bb.0: # %entry
1112; CHECK-NEXT:    pushq %rax
1113; CHECK-NEXT:    callq __extendhfsf2@PLT
1114; CHECK-NEXT:    cvttss2si %xmm0, %rax
1115; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
1116; CHECK-NEXT:    movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
1117; CHECK-NEXT:    cmovaeq %rax, %rcx
1118; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
1119; CHECK-NEXT:    movabsq $9223372036854775807, %rdx # imm = 0x7FFFFFFFFFFFFFFF
1120; CHECK-NEXT:    cmovbeq %rcx, %rdx
1121; CHECK-NEXT:    xorl %eax, %eax
1122; CHECK-NEXT:    ucomiss %xmm0, %xmm0
1123; CHECK-NEXT:    cmovnpq %rdx, %rax
1124; CHECK-NEXT:    popq %rcx
1125; CHECK-NEXT:    retq
1126entry:
1127  %conv = fptosi half %x to i128
1128  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1129  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1130  %conv6 = trunc i128 %spec.store.select7 to i64
1131  ret i64 %conv6
1132}
1133
1134define i64 @utesth_f16i64_mm(half %x) nounwind {
1135; CHECK-LABEL: utesth_f16i64_mm:
1136; CHECK:       # %bb.0: # %entry
1137; CHECK-NEXT:    pushq %rax
1138; CHECK-NEXT:    callq __fixunshfti@PLT
1139; CHECK-NEXT:    xorl %ecx, %ecx
1140; CHECK-NEXT:    testq %rdx, %rdx
1141; CHECK-NEXT:    cmovneq %rcx, %rax
1142; CHECK-NEXT:    popq %rcx
1143; CHECK-NEXT:    retq
1144entry:
1145  %conv = fptoui half %x to i128
1146  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1147  %conv6 = trunc i128 %spec.store.select to i64
1148  ret i64 %conv6
1149}
1150
1151define i64 @ustest_f16i64_mm(half %x) nounwind {
1152; CHECK-LABEL: ustest_f16i64_mm:
1153; CHECK:       # %bb.0: # %entry
1154; CHECK-NEXT:    pushq %rax
1155; CHECK-NEXT:    callq __fixhfti@PLT
1156; CHECK-NEXT:    xorl %ecx, %ecx
1157; CHECK-NEXT:    testq %rdx, %rdx
1158; CHECK-NEXT:    cmovgq %rcx, %rax
1159; CHECK-NEXT:    movl $1, %esi
1160; CHECK-NEXT:    cmovleq %rdx, %rsi
1161; CHECK-NEXT:    testq %rsi, %rsi
1162; CHECK-NEXT:    cmovsq %rcx, %rax
1163; CHECK-NEXT:    popq %rcx
1164; CHECK-NEXT:    retq
1165entry:
1166  %conv = fptosi half %x to i128
1167  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1168  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1169  %conv6 = trunc i128 %spec.store.select7 to i64
1170  ret i64 %conv6
1171}
1172
1173declare i32 @llvm.smin.i32(i32, i32)
1174declare i32 @llvm.smax.i32(i32, i32)
1175declare i32 @llvm.umin.i32(i32, i32)
1176declare i64 @llvm.smin.i64(i64, i64)
1177declare i64 @llvm.smax.i64(i64, i64)
1178declare i64 @llvm.umin.i64(i64, i64)
1179declare i128 @llvm.smin.i128(i128, i128)
1180declare i128 @llvm.smax.i128(i128, i128)
1181declare i128 @llvm.umin.i128(i128, i128)
1182