xref: /llvm-project/llvm/test/CodeGen/WebAssembly/fpclamptosat.ll (revision e665e781dc3f8fac0400f6ac8e168805b0cdf74a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=wasm32-unknown-unknown -mattr=+simd128,+nontrapping-fptoint | FileCheck %s
3
4; i32 saturate
5
6define i32 @stest_f64i32(double %x) {
7; CHECK-LABEL: stest_f64i32:
8; CHECK:         .functype stest_f64i32 (f64) -> (i32)
9; CHECK-NEXT:  # %bb.0: # %entry
10; CHECK-NEXT:    local.get 0
11; CHECK-NEXT:    i32.trunc_sat_f64_s
12; CHECK-NEXT:    # fallthrough-return
13entry:
14  %conv = fptosi double %x to i64
15  %0 = icmp slt i64 %conv, 2147483647
16  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
17  %1 = icmp sgt i64 %spec.store.select, -2147483648
18  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
19  %conv6 = trunc i64 %spec.store.select7 to i32
20  ret i32 %conv6
21}
22
23define i32 @utest_f64i32(double %x) {
24; CHECK-LABEL: utest_f64i32:
25; CHECK:         .functype utest_f64i32 (f64) -> (i32)
26; CHECK-NEXT:  # %bb.0: # %entry
27; CHECK-NEXT:    local.get 0
28; CHECK-NEXT:    i32.trunc_sat_f64_u
29; CHECK-NEXT:    # fallthrough-return
30entry:
31  %conv = fptoui double %x to i64
32  %0 = icmp ult i64 %conv, 4294967295
33  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
34  %conv6 = trunc i64 %spec.store.select to i32
35  ret i32 %conv6
36}
37
38define i32 @ustest_f64i32(double %x) {
39; CHECK-LABEL: ustest_f64i32:
40; CHECK:         .functype ustest_f64i32 (f64) -> (i32)
41; CHECK-NEXT:  # %bb.0: # %entry
42; CHECK-NEXT:    local.get 0
43; CHECK-NEXT:    i32.trunc_sat_f64_u
44; CHECK-NEXT:    # fallthrough-return
45entry:
46  %conv = fptosi double %x to i64
47  %0 = icmp slt i64 %conv, 4294967295
48  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
49  %1 = icmp sgt i64 %spec.store.select, 0
50  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
51  %conv6 = trunc i64 %spec.store.select7 to i32
52  ret i32 %conv6
53}
54
55define i32 @stest_f32i32(float %x) {
56; CHECK-LABEL: stest_f32i32:
57; CHECK:         .functype stest_f32i32 (f32) -> (i32)
58; CHECK-NEXT:  # %bb.0: # %entry
59; CHECK-NEXT:    local.get 0
60; CHECK-NEXT:    i32.trunc_sat_f32_s
61; CHECK-NEXT:    # fallthrough-return
62entry:
63  %conv = fptosi float %x to i64
64  %0 = icmp slt i64 %conv, 2147483647
65  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
66  %1 = icmp sgt i64 %spec.store.select, -2147483648
67  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
68  %conv6 = trunc i64 %spec.store.select7 to i32
69  ret i32 %conv6
70}
71
72define i32 @utest_f32i32(float %x) {
73; CHECK-LABEL: utest_f32i32:
74; CHECK:         .functype utest_f32i32 (f32) -> (i32)
75; CHECK-NEXT:  # %bb.0: # %entry
76; CHECK-NEXT:    local.get 0
77; CHECK-NEXT:    i32.trunc_sat_f32_u
78; CHECK-NEXT:    # fallthrough-return
79entry:
80  %conv = fptoui float %x to i64
81  %0 = icmp ult i64 %conv, 4294967295
82  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
83  %conv6 = trunc i64 %spec.store.select to i32
84  ret i32 %conv6
85}
86
87define i32 @ustest_f32i32(float %x) {
88; CHECK-LABEL: ustest_f32i32:
89; CHECK:         .functype ustest_f32i32 (f32) -> (i32)
90; CHECK-NEXT:  # %bb.0: # %entry
91; CHECK-NEXT:    local.get 0
92; CHECK-NEXT:    i32.trunc_sat_f32_u
93; CHECK-NEXT:    # fallthrough-return
94entry:
95  %conv = fptosi float %x to i64
96  %0 = icmp slt i64 %conv, 4294967295
97  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
98  %1 = icmp sgt i64 %spec.store.select, 0
99  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
100  %conv6 = trunc i64 %spec.store.select7 to i32
101  ret i32 %conv6
102}
103
104define i32 @stest_f16i32(half %x) {
105; CHECK-LABEL: stest_f16i32:
106; CHECK:         .functype stest_f16i32 (f32) -> (i32)
107; CHECK-NEXT:  # %bb.0: # %entry
108; CHECK-NEXT:    local.get 0
109; CHECK-NEXT:    call __truncsfhf2
110; CHECK-NEXT:    call __extendhfsf2
111; CHECK-NEXT:    i32.trunc_sat_f32_s
112; CHECK-NEXT:    # fallthrough-return
113entry:
114  %conv = fptosi half %x to i64
115  %0 = icmp slt i64 %conv, 2147483647
116  %spec.store.select = select i1 %0, i64 %conv, i64 2147483647
117  %1 = icmp sgt i64 %spec.store.select, -2147483648
118  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 -2147483648
119  %conv6 = trunc i64 %spec.store.select7 to i32
120  ret i32 %conv6
121}
122
123define i32 @stest_f16i32_cse(half %x) {
124; CHECK-LABEL: stest_f16i32_cse:
125; CHECK:         .functype stest_f16i32_cse (f32) -> (i32)
126; CHECK-NEXT:  # %bb.0: # %entry
127; CHECK-NEXT:    local.get 0
128; CHECK-NEXT:    call __truncsfhf2
129; CHECK-NEXT:    call __extendhfsf2
130; CHECK-NEXT:    i64.trunc_sat_f32_s
131; CHECK-NEXT:    i32.wrap_i64
132; CHECK-NEXT:    # fallthrough-return
133entry:
134  %conv = fptosi half %x to i64
135  %conv6 = trunc i64 %conv to i32
136  ret i32 %conv6
137}
138
139define i32 @utesth_f16i32(half %x) {
140; CHECK-LABEL: utesth_f16i32:
141; CHECK:         .functype utesth_f16i32 (f32) -> (i32)
142; CHECK-NEXT:  # %bb.0: # %entry
143; CHECK-NEXT:    local.get 0
144; CHECK-NEXT:    call __truncsfhf2
145; CHECK-NEXT:    call __extendhfsf2
146; CHECK-NEXT:    i32.trunc_sat_f32_u
147; CHECK-NEXT:    # fallthrough-return
148entry:
149  %conv = fptoui half %x to i64
150  %0 = icmp ult i64 %conv, 4294967295
151  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
152  %conv6 = trunc i64 %spec.store.select to i32
153  ret i32 %conv6
154}
155
156define i32 @utesth_f16i32_cse(half %x) {
157; CHECK-LABEL: utesth_f16i32_cse:
158; CHECK:         .functype utesth_f16i32_cse (f32) -> (i32)
159; CHECK-NEXT:  # %bb.0: # %entry
160; CHECK-NEXT:    local.get 0
161; CHECK-NEXT:    call __truncsfhf2
162; CHECK-NEXT:    call __extendhfsf2
163; CHECK-NEXT:    i64.trunc_sat_f32_u
164; CHECK-NEXT:    i32.wrap_i64
165; CHECK-NEXT:    # fallthrough-return
166entry:
167  %conv = fptoui half %x to i64
168  %conv6 = trunc i64 %conv to i32
169  ret i32 %conv6
170}
171
172define i32 @ustest_f16i32(half %x) {
173; CHECK-LABEL: ustest_f16i32:
174; CHECK:         .functype ustest_f16i32 (f32) -> (i32)
175; CHECK-NEXT:  # %bb.0: # %entry
176; CHECK-NEXT:    local.get 0
177; CHECK-NEXT:    call __truncsfhf2
178; CHECK-NEXT:    call __extendhfsf2
179; CHECK-NEXT:    i32.trunc_sat_f32_u
180; CHECK-NEXT:    # fallthrough-return
181entry:
182  %conv = fptosi half %x to i64
183  %0 = icmp slt i64 %conv, 4294967295
184  %spec.store.select = select i1 %0, i64 %conv, i64 4294967295
185  %1 = icmp sgt i64 %spec.store.select, 0
186  %spec.store.select7 = select i1 %1, i64 %spec.store.select, i64 0
187  %conv6 = trunc i64 %spec.store.select7 to i32
188  ret i32 %conv6
189}
190
191define i32 @ustest_f16i32_cse(half %x) {
192; CHECK-LABEL: ustest_f16i32_cse:
193; CHECK:         .functype ustest_f16i32_cse (f32) -> (i32)
194; CHECK-NEXT:  # %bb.0: # %entry
195; CHECK-NEXT:    local.get 0
196; CHECK-NEXT:    call __truncsfhf2
197; CHECK-NEXT:    call __extendhfsf2
198; CHECK-NEXT:    i32.trunc_sat_f32_u
199; CHECK-NEXT:    # fallthrough-return
200entry:
201  %conv = fptosi half %x to i64
202  %0 = icmp sgt i64 %conv, 0
203  %spec.store.select7 = select i1 %0, i64 %conv, i64 0
204  %conv6 = trunc i64 %spec.store.select7 to i32
205  ret i32 %conv6
206}
207
208; i16 saturate
209
210define i16 @stest_f64i16(double %x) {
211; CHECK-LABEL: stest_f64i16:
212; CHECK:         .functype stest_f64i16 (f64) -> (i32)
213; CHECK-NEXT:    .local i32
214; CHECK-NEXT:  # %bb.0: # %entry
215; CHECK-NEXT:    local.get 0
216; CHECK-NEXT:    i32.trunc_sat_f64_s
217; CHECK-NEXT:    local.tee 1
218; CHECK-NEXT:    i32.const 32767
219; CHECK-NEXT:    local.get 1
220; CHECK-NEXT:    i32.const 32767
221; CHECK-NEXT:    i32.lt_s
222; CHECK-NEXT:    i32.select
223; CHECK-NEXT:    local.tee 1
224; CHECK-NEXT:    i32.const -32768
225; CHECK-NEXT:    local.get 1
226; CHECK-NEXT:    i32.const -32768
227; CHECK-NEXT:    i32.gt_s
228; CHECK-NEXT:    i32.select
229; CHECK-NEXT:    # fallthrough-return
230entry:
231  %conv = fptosi double %x to i32
232  %0 = icmp slt i32 %conv, 32767
233  %spec.store.select = select i1 %0, i32 %conv, i32 32767
234  %1 = icmp sgt i32 %spec.store.select, -32768
235  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
236  %conv6 = trunc i32 %spec.store.select7 to i16
237  ret i16 %conv6
238}
239
240define i16 @utest_f64i16(double %x) {
241; CHECK-LABEL: utest_f64i16:
242; CHECK:         .functype utest_f64i16 (f64) -> (i32)
243; CHECK-NEXT:    .local i32
244; CHECK-NEXT:  # %bb.0: # %entry
245; CHECK-NEXT:    local.get 0
246; CHECK-NEXT:    i32.trunc_sat_f64_u
247; CHECK-NEXT:    local.tee 1
248; CHECK-NEXT:    i32.const 65535
249; CHECK-NEXT:    local.get 1
250; CHECK-NEXT:    i32.const 65535
251; CHECK-NEXT:    i32.lt_u
252; CHECK-NEXT:    i32.select
253; CHECK-NEXT:    # fallthrough-return
254entry:
255  %conv = fptoui double %x to i32
256  %0 = icmp ult i32 %conv, 65535
257  %spec.store.select = select i1 %0, i32 %conv, i32 65535
258  %conv6 = trunc i32 %spec.store.select to i16
259  ret i16 %conv6
260}
261
262define i16 @ustest_f64i16(double %x) {
263; CHECK-LABEL: ustest_f64i16:
264; CHECK:         .functype ustest_f64i16 (f64) -> (i32)
265; CHECK-NEXT:    .local i32
266; CHECK-NEXT:  # %bb.0: # %entry
267; CHECK-NEXT:    local.get 0
268; CHECK-NEXT:    i32.trunc_sat_f64_s
269; CHECK-NEXT:    local.tee 1
270; CHECK-NEXT:    i32.const 65535
271; CHECK-NEXT:    local.get 1
272; CHECK-NEXT:    i32.const 65535
273; CHECK-NEXT:    i32.lt_s
274; CHECK-NEXT:    i32.select
275; CHECK-NEXT:    local.tee 1
276; CHECK-NEXT:    i32.const 0
277; CHECK-NEXT:    local.get 1
278; CHECK-NEXT:    i32.const 0
279; CHECK-NEXT:    i32.gt_s
280; CHECK-NEXT:    i32.select
281; CHECK-NEXT:    # fallthrough-return
282entry:
283  %conv = fptosi double %x to i32
284  %0 = icmp slt i32 %conv, 65535
285  %spec.store.select = select i1 %0, i32 %conv, i32 65535
286  %1 = icmp sgt i32 %spec.store.select, 0
287  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
288  %conv6 = trunc i32 %spec.store.select7 to i16
289  ret i16 %conv6
290}
291
292define i16 @stest_f32i16(float %x) {
293; CHECK-LABEL: stest_f32i16:
294; CHECK:         .functype stest_f32i16 (f32) -> (i32)
295; CHECK-NEXT:    .local i32
296; CHECK-NEXT:  # %bb.0: # %entry
297; CHECK-NEXT:    local.get 0
298; CHECK-NEXT:    i32.trunc_sat_f32_s
299; CHECK-NEXT:    local.tee 1
300; CHECK-NEXT:    i32.const 32767
301; CHECK-NEXT:    local.get 1
302; CHECK-NEXT:    i32.const 32767
303; CHECK-NEXT:    i32.lt_s
304; CHECK-NEXT:    i32.select
305; CHECK-NEXT:    local.tee 1
306; CHECK-NEXT:    i32.const -32768
307; CHECK-NEXT:    local.get 1
308; CHECK-NEXT:    i32.const -32768
309; CHECK-NEXT:    i32.gt_s
310; CHECK-NEXT:    i32.select
311; CHECK-NEXT:    # fallthrough-return
312entry:
313  %conv = fptosi float %x to i32
314  %0 = icmp slt i32 %conv, 32767
315  %spec.store.select = select i1 %0, i32 %conv, i32 32767
316  %1 = icmp sgt i32 %spec.store.select, -32768
317  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
318  %conv6 = trunc i32 %spec.store.select7 to i16
319  ret i16 %conv6
320}
321
322define i16 @utest_f32i16(float %x) {
323; CHECK-LABEL: utest_f32i16:
324; CHECK:         .functype utest_f32i16 (f32) -> (i32)
325; CHECK-NEXT:    .local i32
326; CHECK-NEXT:  # %bb.0: # %entry
327; CHECK-NEXT:    local.get 0
328; CHECK-NEXT:    i32.trunc_sat_f32_u
329; CHECK-NEXT:    local.tee 1
330; CHECK-NEXT:    i32.const 65535
331; CHECK-NEXT:    local.get 1
332; CHECK-NEXT:    i32.const 65535
333; CHECK-NEXT:    i32.lt_u
334; CHECK-NEXT:    i32.select
335; CHECK-NEXT:    # fallthrough-return
336entry:
337  %conv = fptoui float %x to i32
338  %0 = icmp ult i32 %conv, 65535
339  %spec.store.select = select i1 %0, i32 %conv, i32 65535
340  %conv6 = trunc i32 %spec.store.select to i16
341  ret i16 %conv6
342}
343
344define i16 @ustest_f32i16(float %x) {
345; CHECK-LABEL: ustest_f32i16:
346; CHECK:         .functype ustest_f32i16 (f32) -> (i32)
347; CHECK-NEXT:    .local i32
348; CHECK-NEXT:  # %bb.0: # %entry
349; CHECK-NEXT:    local.get 0
350; CHECK-NEXT:    i32.trunc_sat_f32_s
351; CHECK-NEXT:    local.tee 1
352; CHECK-NEXT:    i32.const 65535
353; CHECK-NEXT:    local.get 1
354; CHECK-NEXT:    i32.const 65535
355; CHECK-NEXT:    i32.lt_s
356; CHECK-NEXT:    i32.select
357; CHECK-NEXT:    local.tee 1
358; CHECK-NEXT:    i32.const 0
359; CHECK-NEXT:    local.get 1
360; CHECK-NEXT:    i32.const 0
361; CHECK-NEXT:    i32.gt_s
362; CHECK-NEXT:    i32.select
363; CHECK-NEXT:    # fallthrough-return
364entry:
365  %conv = fptosi float %x to i32
366  %0 = icmp slt i32 %conv, 65535
367  %spec.store.select = select i1 %0, i32 %conv, i32 65535
368  %1 = icmp sgt i32 %spec.store.select, 0
369  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
370  %conv6 = trunc i32 %spec.store.select7 to i16
371  ret i16 %conv6
372}
373
374define i16 @stest_f16i16(half %x) {
375; CHECK-LABEL: stest_f16i16:
376; CHECK:         .functype stest_f16i16 (f32) -> (i32)
377; CHECK-NEXT:    .local i32
378; CHECK-NEXT:  # %bb.0: # %entry
379; CHECK-NEXT:    local.get 0
380; CHECK-NEXT:    call __truncsfhf2
381; CHECK-NEXT:    call __extendhfsf2
382; CHECK-NEXT:    i32.trunc_sat_f32_s
383; CHECK-NEXT:    local.tee 1
384; CHECK-NEXT:    i32.const 32767
385; CHECK-NEXT:    local.get 1
386; CHECK-NEXT:    i32.const 32767
387; CHECK-NEXT:    i32.lt_s
388; CHECK-NEXT:    i32.select
389; CHECK-NEXT:    local.tee 1
390; CHECK-NEXT:    i32.const -32768
391; CHECK-NEXT:    local.get 1
392; CHECK-NEXT:    i32.const -32768
393; CHECK-NEXT:    i32.gt_s
394; CHECK-NEXT:    i32.select
395; CHECK-NEXT:    # fallthrough-return
396entry:
397  %conv = fptosi half %x to i32
398  %0 = icmp slt i32 %conv, 32767
399  %spec.store.select = select i1 %0, i32 %conv, i32 32767
400  %1 = icmp sgt i32 %spec.store.select, -32768
401  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 -32768
402  %conv6 = trunc i32 %spec.store.select7 to i16
403  ret i16 %conv6
404}
405
406define i16 @utesth_f16i16(half %x) {
407; CHECK-LABEL: utesth_f16i16:
408; CHECK:         .functype utesth_f16i16 (f32) -> (i32)
409; CHECK-NEXT:    .local i32
410; CHECK-NEXT:  # %bb.0: # %entry
411; CHECK-NEXT:    local.get 0
412; CHECK-NEXT:    call __truncsfhf2
413; CHECK-NEXT:    call __extendhfsf2
414; CHECK-NEXT:    i32.trunc_sat_f32_u
415; CHECK-NEXT:    local.tee 1
416; CHECK-NEXT:    i32.const 65535
417; CHECK-NEXT:    local.get 1
418; CHECK-NEXT:    i32.const 65535
419; CHECK-NEXT:    i32.lt_u
420; CHECK-NEXT:    i32.select
421; CHECK-NEXT:    # fallthrough-return
422entry:
423  %conv = fptoui half %x to i32
424  %0 = icmp ult i32 %conv, 65535
425  %spec.store.select = select i1 %0, i32 %conv, i32 65535
426  %conv6 = trunc i32 %spec.store.select to i16
427  ret i16 %conv6
428}
429
430define i16 @utesth_f16i16_cse(half %x) {
431; CHECK-LABEL: utesth_f16i16_cse:
432; CHECK:         .functype utesth_f16i16_cse (f32) -> (i32)
433; CHECK-NEXT:  # %bb.0: # %entry
434; CHECK-NEXT:    local.get 0
435; CHECK-NEXT:    call __truncsfhf2
436; CHECK-NEXT:    call __extendhfsf2
437; CHECK-NEXT:    i32.trunc_sat_f32_u
438; CHECK-NEXT:    # fallthrough-return
439entry:
440  %conv = fptoui half %x to i32
441  %conv6 = trunc i32 %conv to i16
442  ret i16 %conv6
443}
444
445define i16 @ustest_f16i16(half %x) {
446; CHECK-LABEL: ustest_f16i16:
447; CHECK:         .functype ustest_f16i16 (f32) -> (i32)
448; CHECK-NEXT:    .local i32
449; CHECK-NEXT:  # %bb.0: # %entry
450; CHECK-NEXT:    local.get 0
451; CHECK-NEXT:    call __truncsfhf2
452; CHECK-NEXT:    call __extendhfsf2
453; CHECK-NEXT:    i32.trunc_sat_f32_s
454; CHECK-NEXT:    local.tee 1
455; CHECK-NEXT:    i32.const 65535
456; CHECK-NEXT:    local.get 1
457; CHECK-NEXT:    i32.const 65535
458; CHECK-NEXT:    i32.lt_s
459; CHECK-NEXT:    i32.select
460; CHECK-NEXT:    local.tee 1
461; CHECK-NEXT:    i32.const 0
462; CHECK-NEXT:    local.get 1
463; CHECK-NEXT:    i32.const 0
464; CHECK-NEXT:    i32.gt_s
465; CHECK-NEXT:    i32.select
466; CHECK-NEXT:    # fallthrough-return
467entry:
468  %conv = fptosi half %x to i32
469  %0 = icmp slt i32 %conv, 65535
470  %spec.store.select = select i1 %0, i32 %conv, i32 65535
471  %1 = icmp sgt i32 %spec.store.select, 0
472  %spec.store.select7 = select i1 %1, i32 %spec.store.select, i32 0
473  %conv6 = trunc i32 %spec.store.select7 to i16
474  ret i16 %conv6
475}
476
477define i16 @ustest_f16i16_cse(half %x) {
478; CHECK-LABEL: ustest_f16i16_cse:
479; CHECK:         .functype ustest_f16i16_cse (f32) -> (i32)
480; CHECK-NEXT:  # %bb.0: # %entry
481; CHECK-NEXT:    local.get 0
482; CHECK-NEXT:    call __truncsfhf2
483; CHECK-NEXT:    call __extendhfsf2
484; CHECK-NEXT:    i32.trunc_sat_f32_u
485; CHECK-NEXT:    # fallthrough-return
486entry:
487  %conv = fptosi half %x to i32
488  %0 = icmp sgt i32 %conv, 0
489  %spec.store.select7 = select i1 %0, i32 %conv, i32 0
490  %conv6 = trunc i32 %spec.store.select7 to i16
491  ret i16 %conv6
492}
493
494; i64 saturate
495
496define i64 @stest_f64i64(double %x) {
497; CHECK-LABEL: stest_f64i64:
498; CHECK:         .functype stest_f64i64 (f64) -> (i64)
499; CHECK-NEXT:  # %bb.0: # %entry
500; CHECK-NEXT:    local.get 0
501; CHECK-NEXT:    i64.trunc_sat_f64_s
502; CHECK-NEXT:    # fallthrough-return
503entry:
504  %conv = fptosi double %x to i128
505  %0 = icmp slt i128 %conv, 9223372036854775807
506  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
507  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
508  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
509  %conv6 = trunc i128 %spec.store.select7 to i64
510  ret i64 %conv6
511}
512
513define i64 @utest_f64i64(double %x) {
514; CHECK-LABEL: utest_f64i64:
515; CHECK:         .functype utest_f64i64 (f64) -> (i64)
516; CHECK-NEXT:    .local i32, i64, i64
517; CHECK-NEXT:  # %bb.0: # %entry
518; CHECK-NEXT:    global.get __stack_pointer
519; CHECK-NEXT:    i32.const 16
520; CHECK-NEXT:    i32.sub
521; CHECK-NEXT:    local.tee 1
522; CHECK-NEXT:    global.set __stack_pointer
523; CHECK-NEXT:    local.get 1
524; CHECK-NEXT:    local.get 0
525; CHECK-NEXT:    call __fixunsdfti
526; CHECK-NEXT:    local.get 1
527; CHECK-NEXT:    i64.load 8
528; CHECK-NEXT:    local.set 2
529; CHECK-NEXT:    local.get 1
530; CHECK-NEXT:    i64.load 0
531; CHECK-NEXT:    local.set 3
532; CHECK-NEXT:    local.get 1
533; CHECK-NEXT:    i32.const 16
534; CHECK-NEXT:    i32.add
535; CHECK-NEXT:    global.set __stack_pointer
536; CHECK-NEXT:    local.get 3
537; CHECK-NEXT:    i64.const 0
538; CHECK-NEXT:    local.get 2
539; CHECK-NEXT:    i64.eqz
540; CHECK-NEXT:    i64.select
541; CHECK-NEXT:    # fallthrough-return
542entry:
543  %conv = fptoui double %x to i128
544  %0 = icmp ult i128 %conv, 18446744073709551616
545  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
546  %conv6 = trunc i128 %spec.store.select to i64
547  ret i64 %conv6
548}
549
550define i64 @utest_f64i64_cse_combine(double %x) #0 {
551; CHECK-LABEL: utest_f64i64_cse_combine:
552; CHECK:         .functype utest_f64i64_cse_combine (f64) -> (i64)
553; CHECK-NEXT:    .local i32, i64, i64
554; CHECK-NEXT:  # %bb.0: # %entry
555; CHECK-NEXT:    global.get __stack_pointer
556; CHECK-NEXT:    i32.const 16
557; CHECK-NEXT:    i32.sub
558; CHECK-NEXT:    local.tee 1
559; CHECK-NEXT:    global.set __stack_pointer
560; CHECK-NEXT:    local.get 1
561; CHECK-NEXT:    local.get 0
562; CHECK-NEXT:    call __fixunsdfti
563; CHECK-NEXT:    local.get 1
564; CHECK-NEXT:    i64.load 8
565; CHECK-NEXT:    local.set 2
566; CHECK-NEXT:    local.get 1
567; CHECK-NEXT:    i64.load 0
568; CHECK-NEXT:    local.set 3
569; CHECK-NEXT:    local.get 1
570; CHECK-NEXT:    i32.const 16
571; CHECK-NEXT:    i32.add
572; CHECK-NEXT:    global.set __stack_pointer
573; CHECK-NEXT:    local.get 3
574; CHECK-NEXT:    i64.const 0
575; CHECK-NEXT:    local.get 2
576; CHECK-NEXT:    i64.eqz
577; CHECK-NEXT:    i64.select
578; CHECK-NEXT:    # fallthrough-return
579entry:
580  %conv = fptoui double %x to i128
581  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
582  %conv6 = trunc i128 %spec.store.select to i64
583  ret i64 %conv6
584}
585
586
587define i64 @ustest_f64i64(double %x) {
588; CHECK-LABEL: ustest_f64i64:
589; CHECK:         .functype ustest_f64i64 (f64) -> (i64)
590; CHECK-NEXT:    .local i32, i64, i64
591; CHECK-NEXT:  # %bb.0: # %entry
592; CHECK-NEXT:    global.get __stack_pointer
593; CHECK-NEXT:    i32.const 16
594; CHECK-NEXT:    i32.sub
595; CHECK-NEXT:    local.tee 1
596; CHECK-NEXT:    global.set __stack_pointer
597; CHECK-NEXT:    local.get 1
598; CHECK-NEXT:    local.get 0
599; CHECK-NEXT:    call __fixdfti
600; CHECK-NEXT:    local.get 1
601; CHECK-NEXT:    i64.load 8
602; CHECK-NEXT:    local.set 2
603; CHECK-NEXT:    local.get 1
604; CHECK-NEXT:    i64.load 0
605; CHECK-NEXT:    local.set 3
606; CHECK-NEXT:    local.get 1
607; CHECK-NEXT:    i32.const 16
608; CHECK-NEXT:    i32.add
609; CHECK-NEXT:    global.set __stack_pointer
610; CHECK-NEXT:    local.get 3
611; CHECK-NEXT:    i64.const 0
612; CHECK-NEXT:    local.get 2
613; CHECK-NEXT:    i64.const 1
614; CHECK-NEXT:    i64.lt_s
615; CHECK-NEXT:    local.tee 1
616; CHECK-NEXT:    i64.select
617; CHECK-NEXT:    local.tee 3
618; CHECK-NEXT:    i64.const 0
619; CHECK-NEXT:    local.get 3
620; CHECK-NEXT:    i64.const 0
621; CHECK-NEXT:    i64.ne
622; CHECK-NEXT:    local.get 2
623; CHECK-NEXT:    i64.const 1
624; CHECK-NEXT:    local.get 1
625; CHECK-NEXT:    i64.select
626; CHECK-NEXT:    local.tee 2
627; CHECK-NEXT:    i64.const 0
628; CHECK-NEXT:    i64.gt_s
629; CHECK-NEXT:    local.get 2
630; CHECK-NEXT:    i64.eqz
631; CHECK-NEXT:    i32.select
632; CHECK-NEXT:    i64.select
633; CHECK-NEXT:    # fallthrough-return
634entry:
635  %conv = fptosi double %x to i128
636  %0 = icmp slt i128 %conv, 18446744073709551616
637  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
638  %1 = icmp sgt i128 %spec.store.select, 0
639  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
640  %conv6 = trunc i128 %spec.store.select7 to i64
641  ret i64 %conv6
642}
643
644define i64 @ustest_f64i64_cse_combine(double %x) #0 {
645; CHECK-LABEL: ustest_f64i64_cse_combine:
646; CHECK:         .functype ustest_f64i64_cse_combine (f64) -> (i64)
647; CHECK-NEXT:    .local i32, i64, i64
648; CHECK-NEXT:  # %bb.0: # %entry
649; CHECK-NEXT:    global.get __stack_pointer
650; CHECK-NEXT:    i32.const 16
651; CHECK-NEXT:    i32.sub
652; CHECK-NEXT:    local.tee 1
653; CHECK-NEXT:    global.set __stack_pointer
654; CHECK-NEXT:    local.get 1
655; CHECK-NEXT:    local.get 0
656; CHECK-NEXT:    call __fixdfti
657; CHECK-NEXT:    local.get 1
658; CHECK-NEXT:    i64.load 8
659; CHECK-NEXT:    local.set 2
660; CHECK-NEXT:    local.get 1
661; CHECK-NEXT:    i64.load 0
662; CHECK-NEXT:    local.set 3
663; CHECK-NEXT:    local.get 1
664; CHECK-NEXT:    i32.const 16
665; CHECK-NEXT:    i32.add
666; CHECK-NEXT:    global.set __stack_pointer
667; CHECK-NEXT:    i64.const 0
668; CHECK-NEXT:    local.get 3
669; CHECK-NEXT:    i64.const 0
670; CHECK-NEXT:    local.get 2
671; CHECK-NEXT:    i64.const 1
672; CHECK-NEXT:    i64.lt_s
673; CHECK-NEXT:    local.tee 1
674; CHECK-NEXT:    i64.select
675; CHECK-NEXT:    local.get 2
676; CHECK-NEXT:    i64.const 1
677; CHECK-NEXT:    local.get 1
678; CHECK-NEXT:    i64.select
679; CHECK-NEXT:    i64.const 0
680; CHECK-NEXT:    i64.lt_s
681; CHECK-NEXT:    i64.select
682; CHECK-NEXT:    # fallthrough-return
683entry:
684  %conv = fptosi double %x to i128
685  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
686  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
687  %conv6 = trunc i128 %spec.store.select7 to i64
688  ret i64 %conv6
689}
690
691define i64 @stest_f32i64(float %x) {
692; CHECK-LABEL: stest_f32i64:
693; CHECK:         .functype stest_f32i64 (f32) -> (i64)
694; CHECK-NEXT:  # %bb.0: # %entry
695; CHECK-NEXT:    local.get 0
696; CHECK-NEXT:    i64.trunc_sat_f32_s
697; CHECK-NEXT:    # fallthrough-return
698entry:
699  %conv = fptosi float %x to i128
700  %0 = icmp slt i128 %conv, 9223372036854775807
701  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
702  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
703  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
704  %conv6 = trunc i128 %spec.store.select7 to i64
705  ret i64 %conv6
706}
707
708define i64 @utest_f32i64(float %x) {
709; CHECK-LABEL: utest_f32i64:
710; CHECK:         .functype utest_f32i64 (f32) -> (i64)
711; CHECK-NEXT:    .local i32, i64, i64
712; CHECK-NEXT:  # %bb.0: # %entry
713; CHECK-NEXT:    global.get __stack_pointer
714; CHECK-NEXT:    i32.const 16
715; CHECK-NEXT:    i32.sub
716; CHECK-NEXT:    local.tee 1
717; CHECK-NEXT:    global.set __stack_pointer
718; CHECK-NEXT:    local.get 1
719; CHECK-NEXT:    local.get 0
720; CHECK-NEXT:    call __fixunssfti
721; CHECK-NEXT:    local.get 1
722; CHECK-NEXT:    i64.load 8
723; CHECK-NEXT:    local.set 2
724; CHECK-NEXT:    local.get 1
725; CHECK-NEXT:    i64.load 0
726; CHECK-NEXT:    local.set 3
727; CHECK-NEXT:    local.get 1
728; CHECK-NEXT:    i32.const 16
729; CHECK-NEXT:    i32.add
730; CHECK-NEXT:    global.set __stack_pointer
731; CHECK-NEXT:    local.get 3
732; CHECK-NEXT:    i64.const 0
733; CHECK-NEXT:    local.get 2
734; CHECK-NEXT:    i64.eqz
735; CHECK-NEXT:    i64.select
736; CHECK-NEXT:    # fallthrough-return
737entry:
738  %conv = fptoui float %x to i128
739  %0 = icmp ult i128 %conv, 18446744073709551616
740  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
741  %conv6 = trunc i128 %spec.store.select to i64
742  ret i64 %conv6
743}
744
745define i64 @stest_f32i64_cse_combine(float %x) #0 {
746; CHECK-LABEL: stest_f32i64_cse_combine:
747; CHECK:         .functype stest_f32i64_cse_combine (f32) -> (i64)
748; CHECK-NEXT:  # %bb.0: # %entry
749; CHECK-NEXT:    local.get 0
750; CHECK-NEXT:    i64.trunc_sat_f32_s
751; CHECK-NEXT:    # fallthrough-return
752entry:
753  %conv = fptosi float %x to i128
754  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
755  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
756  %conv6 = trunc i128 %spec.store.select7 to i64
757  ret i64 %conv6
758}
759
760define i64 @ustest_f32i64(float %x) {
761; CHECK-LABEL: ustest_f32i64:
762; CHECK:         .functype ustest_f32i64 (f32) -> (i64)
763; CHECK-NEXT:    .local i32, i64, i64
764; CHECK-NEXT:  # %bb.0: # %entry
765; CHECK-NEXT:    global.get __stack_pointer
766; CHECK-NEXT:    i32.const 16
767; CHECK-NEXT:    i32.sub
768; CHECK-NEXT:    local.tee 1
769; CHECK-NEXT:    global.set __stack_pointer
770; CHECK-NEXT:    local.get 1
771; CHECK-NEXT:    local.get 0
772; CHECK-NEXT:    call __fixsfti
773; CHECK-NEXT:    local.get 1
774; CHECK-NEXT:    i64.load 8
775; CHECK-NEXT:    local.set 2
776; CHECK-NEXT:    local.get 1
777; CHECK-NEXT:    i64.load 0
778; CHECK-NEXT:    local.set 3
779; CHECK-NEXT:    local.get 1
780; CHECK-NEXT:    i32.const 16
781; CHECK-NEXT:    i32.add
782; CHECK-NEXT:    global.set __stack_pointer
783; CHECK-NEXT:    local.get 3
784; CHECK-NEXT:    i64.const 0
785; CHECK-NEXT:    local.get 2
786; CHECK-NEXT:    i64.const 1
787; CHECK-NEXT:    i64.lt_s
788; CHECK-NEXT:    local.tee 1
789; CHECK-NEXT:    i64.select
790; CHECK-NEXT:    local.tee 3
791; CHECK-NEXT:    i64.const 0
792; CHECK-NEXT:    local.get 3
793; CHECK-NEXT:    i64.const 0
794; CHECK-NEXT:    i64.ne
795; CHECK-NEXT:    local.get 2
796; CHECK-NEXT:    i64.const 1
797; CHECK-NEXT:    local.get 1
798; CHECK-NEXT:    i64.select
799; CHECK-NEXT:    local.tee 2
800; CHECK-NEXT:    i64.const 0
801; CHECK-NEXT:    i64.gt_s
802; CHECK-NEXT:    local.get 2
803; CHECK-NEXT:    i64.eqz
804; CHECK-NEXT:    i32.select
805; CHECK-NEXT:    i64.select
806; CHECK-NEXT:    # fallthrough-return
807entry:
808  %conv = fptosi float %x to i128
809  %0 = icmp slt i128 %conv, 18446744073709551616
810  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
811  %1 = icmp sgt i128 %spec.store.select, 0
812  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
813  %conv6 = trunc i128 %spec.store.select7 to i64
814  ret i64 %conv6
815}
816
817define i64 @ustest_f32i64_cse_combine(float %x) #0 {
818; CHECK-LABEL: ustest_f32i64_cse_combine:
819; CHECK:         .functype ustest_f32i64_cse_combine (f32) -> (i64)
820; CHECK-NEXT:    .local i32, i64, i64
821; CHECK-NEXT:  # %bb.0: # %entry
822; CHECK-NEXT:    global.get __stack_pointer
823; CHECK-NEXT:    i32.const 16
824; CHECK-NEXT:    i32.sub
825; CHECK-NEXT:    local.tee 1
826; CHECK-NEXT:    global.set __stack_pointer
827; CHECK-NEXT:    local.get 1
828; CHECK-NEXT:    local.get 0
829; CHECK-NEXT:    call __fixsfti
830; CHECK-NEXT:    local.get 1
831; CHECK-NEXT:    i64.load 8
832; CHECK-NEXT:    local.set 2
833; CHECK-NEXT:    local.get 1
834; CHECK-NEXT:    i64.load 0
835; CHECK-NEXT:    local.set 3
836; CHECK-NEXT:    local.get 1
837; CHECK-NEXT:    i32.const 16
838; CHECK-NEXT:    i32.add
839; CHECK-NEXT:    global.set __stack_pointer
840; CHECK-NEXT:    i64.const 0
841; CHECK-NEXT:    local.get 3
842; CHECK-NEXT:    i64.const 0
843; CHECK-NEXT:    local.get 2
844; CHECK-NEXT:    i64.const 1
845; CHECK-NEXT:    i64.lt_s
846; CHECK-NEXT:    local.tee 1
847; CHECK-NEXT:    i64.select
848; CHECK-NEXT:    local.get 2
849; CHECK-NEXT:    i64.const 1
850; CHECK-NEXT:    local.get 1
851; CHECK-NEXT:    i64.select
852; CHECK-NEXT:    i64.const 0
853; CHECK-NEXT:    i64.lt_s
854; CHECK-NEXT:    i64.select
855; CHECK-NEXT:    # fallthrough-return
856entry:
857  %conv = fptosi float %x to i128
858  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
859  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
860  %conv6 = trunc i128 %spec.store.select7 to i64
861  ret i64 %conv6
862}
863
864define i64 @stest_f16i64(half %x) {
865; CHECK-LABEL: stest_f16i64:
866; CHECK:         .functype stest_f16i64 (f32) -> (i64)
867; CHECK-NEXT:  # %bb.0: # %entry
868; CHECK-NEXT:    local.get 0
869; CHECK-NEXT:    call __truncsfhf2
870; CHECK-NEXT:    call __extendhfsf2
871; CHECK-NEXT:    i64.trunc_sat_f32_s
872; CHECK-NEXT:    # fallthrough-return
873entry:
874  %conv = fptosi half %x to i128
875  %0 = icmp slt i128 %conv, 9223372036854775807
876  %spec.store.select = select i1 %0, i128 %conv, i128 9223372036854775807
877  %1 = icmp sgt i128 %spec.store.select, -9223372036854775808
878  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 -9223372036854775808
879  %conv6 = trunc i128 %spec.store.select7 to i64
880  ret i64 %conv6
881}
882
883define i64 @utesth_f16i64(half %x) {
884; CHECK-LABEL: utesth_f16i64:
885; CHECK:         .functype utesth_f16i64 (f32) -> (i64)
886; CHECK-NEXT:    .local i32, i64, i64
887; CHECK-NEXT:  # %bb.0: # %entry
888; CHECK-NEXT:    global.get __stack_pointer
889; CHECK-NEXT:    i32.const 16
890; CHECK-NEXT:    i32.sub
891; CHECK-NEXT:    local.tee 1
892; CHECK-NEXT:    global.set __stack_pointer
893; CHECK-NEXT:    local.get 1
894; CHECK-NEXT:    local.get 0
895; CHECK-NEXT:    call __truncsfhf2
896; CHECK-NEXT:    call __extendhfsf2
897; CHECK-NEXT:    call __fixunssfti
898; CHECK-NEXT:    local.get 1
899; CHECK-NEXT:    i64.load 8
900; CHECK-NEXT:    local.set 2
901; CHECK-NEXT:    local.get 1
902; CHECK-NEXT:    i64.load 0
903; CHECK-NEXT:    local.set 3
904; CHECK-NEXT:    local.get 1
905; CHECK-NEXT:    i32.const 16
906; CHECK-NEXT:    i32.add
907; CHECK-NEXT:    global.set __stack_pointer
908; CHECK-NEXT:    local.get 3
909; CHECK-NEXT:    i64.const 0
910; CHECK-NEXT:    local.get 2
911; CHECK-NEXT:    i64.eqz
912; CHECK-NEXT:    i64.select
913; CHECK-NEXT:    # fallthrough-return
914entry:
915  %conv = fptoui half %x to i128
916  %0 = icmp ult i128 %conv, 18446744073709551616
917  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
918  %conv6 = trunc i128 %spec.store.select to i64
919  ret i64 %conv6
920}
921
922define i64 @utesth_f16i64_cse(half %x) {
923; CHECK-LABEL: utesth_f16i64_cse:
924; CHECK:         .functype utesth_f16i64_cse (f32) -> (i64)
925; CHECK-NEXT:    .local i32, i64
926; CHECK-NEXT:  # %bb.0: # %entry
927; CHECK-NEXT:    global.get __stack_pointer
928; CHECK-NEXT:    i32.const 16
929; CHECK-NEXT:    i32.sub
930; CHECK-NEXT:    local.tee 1
931; CHECK-NEXT:    global.set __stack_pointer
932; CHECK-NEXT:    local.get 1
933; CHECK-NEXT:    local.get 0
934; CHECK-NEXT:    call __truncsfhf2
935; CHECK-NEXT:    call __extendhfsf2
936; CHECK-NEXT:    call __fixunssfti
937; CHECK-NEXT:    local.get 1
938; CHECK-NEXT:    i64.load 0
939; CHECK-NEXT:    local.set 2
940; CHECK-NEXT:    local.get 1
941; CHECK-NEXT:    i32.const 16
942; CHECK-NEXT:    i32.add
943; CHECK-NEXT:    global.set __stack_pointer
944; CHECK-NEXT:    local.get 2
945; CHECK-NEXT:    # fallthrough-return
946entry:
947  %conv = fptoui half %x to i128
948  %conv6 = trunc i128 %conv to i64
949  ret i64 %conv6
950}
951
952define i64 @ustest_f16i64(half %x) {
953; CHECK-LABEL: ustest_f16i64:
954; CHECK:         .functype ustest_f16i64 (f32) -> (i64)
955; CHECK-NEXT:    .local i32, i64, i64
956; CHECK-NEXT:  # %bb.0: # %entry
957; CHECK-NEXT:    global.get __stack_pointer
958; CHECK-NEXT:    i32.const 16
959; CHECK-NEXT:    i32.sub
960; CHECK-NEXT:    local.tee 1
961; CHECK-NEXT:    global.set __stack_pointer
962; CHECK-NEXT:    local.get 1
963; CHECK-NEXT:    local.get 0
964; CHECK-NEXT:    call __truncsfhf2
965; CHECK-NEXT:    call __extendhfsf2
966; CHECK-NEXT:    call __fixsfti
967; CHECK-NEXT:    local.get 1
968; CHECK-NEXT:    i64.load 8
969; CHECK-NEXT:    local.set 2
970; CHECK-NEXT:    local.get 1
971; CHECK-NEXT:    i64.load 0
972; CHECK-NEXT:    local.set 3
973; CHECK-NEXT:    local.get 1
974; CHECK-NEXT:    i32.const 16
975; CHECK-NEXT:    i32.add
976; CHECK-NEXT:    global.set __stack_pointer
977; CHECK-NEXT:    local.get 3
978; CHECK-NEXT:    i64.const 0
979; CHECK-NEXT:    local.get 2
980; CHECK-NEXT:    i64.const 1
981; CHECK-NEXT:    i64.lt_s
982; CHECK-NEXT:    local.tee 1
983; CHECK-NEXT:    i64.select
984; CHECK-NEXT:    local.tee 3
985; CHECK-NEXT:    i64.const 0
986; CHECK-NEXT:    local.get 3
987; CHECK-NEXT:    i64.const 0
988; CHECK-NEXT:    i64.ne
989; CHECK-NEXT:    local.get 2
990; CHECK-NEXT:    i64.const 1
991; CHECK-NEXT:    local.get 1
992; CHECK-NEXT:    i64.select
993; CHECK-NEXT:    local.tee 2
994; CHECK-NEXT:    i64.const 0
995; CHECK-NEXT:    i64.gt_s
996; CHECK-NEXT:    local.get 2
997; CHECK-NEXT:    i64.eqz
998; CHECK-NEXT:    i32.select
999; CHECK-NEXT:    i64.select
1000; CHECK-NEXT:    # fallthrough-return
1001entry:
1002  %conv = fptosi half %x to i128
1003  %0 = icmp slt i128 %conv, 18446744073709551616
1004  %spec.store.select = select i1 %0, i128 %conv, i128 18446744073709551616
1005  %1 = icmp sgt i128 %spec.store.select, 0
1006  %spec.store.select7 = select i1 %1, i128 %spec.store.select, i128 0
1007  %conv6 = trunc i128 %spec.store.select7 to i64
1008  ret i64 %conv6
1009}
1010
1011
1012
1013
1014; i32 saturate
1015
1016define i32 @stest_f64i32_mm(double %x) {
1017; CHECK-LABEL: stest_f64i32_mm:
1018; CHECK:         .functype stest_f64i32_mm (f64) -> (i32)
1019; CHECK-NEXT:  # %bb.0: # %entry
1020; CHECK-NEXT:    local.get 0
1021; CHECK-NEXT:    i32.trunc_sat_f64_s
1022; CHECK-NEXT:    # fallthrough-return
1023entry:
1024  %conv = fptosi double %x to i64
1025  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
1026  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
1027  %conv6 = trunc i64 %spec.store.select7 to i32
1028  ret i32 %conv6
1029}
1030
1031define i32 @utest_f64i32_mm(double %x) {
1032; CHECK-LABEL: utest_f64i32_mm:
1033; CHECK:         .functype utest_f64i32_mm (f64) -> (i32)
1034; CHECK-NEXT:  # %bb.0: # %entry
1035; CHECK-NEXT:    local.get 0
1036; CHECK-NEXT:    i32.trunc_sat_f64_u
1037; CHECK-NEXT:    # fallthrough-return
1038entry:
1039  %conv = fptoui double %x to i64
1040  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
1041  %conv6 = trunc i64 %spec.store.select to i32
1042  ret i32 %conv6
1043}
1044
1045define i32 @ustest_f64i32_mm(double %x) {
1046; CHECK-LABEL: ustest_f64i32_mm:
1047; CHECK:         .functype ustest_f64i32_mm (f64) -> (i32)
1048; CHECK-NEXT:  # %bb.0: # %entry
1049; CHECK-NEXT:    local.get 0
1050; CHECK-NEXT:    i32.trunc_sat_f64_u
1051; CHECK-NEXT:    # fallthrough-return
1052entry:
1053  %conv = fptosi double %x to i64
1054  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
1055  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
1056  %conv6 = trunc i64 %spec.store.select7 to i32
1057  ret i32 %conv6
1058}
1059
1060define i32 @stest_f32i32_mm(float %x) {
1061; CHECK-LABEL: stest_f32i32_mm:
1062; CHECK:         .functype stest_f32i32_mm (f32) -> (i32)
1063; CHECK-NEXT:  # %bb.0: # %entry
1064; CHECK-NEXT:    local.get 0
1065; CHECK-NEXT:    i32.trunc_sat_f32_s
1066; CHECK-NEXT:    # fallthrough-return
1067entry:
1068  %conv = fptosi float %x to i64
1069  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
1070  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
1071  %conv6 = trunc i64 %spec.store.select7 to i32
1072  ret i32 %conv6
1073}
1074
1075define i32 @utest_f32i32_mm(float %x) {
1076; CHECK-LABEL: utest_f32i32_mm:
1077; CHECK:         .functype utest_f32i32_mm (f32) -> (i32)
1078; CHECK-NEXT:  # %bb.0: # %entry
1079; CHECK-NEXT:    local.get 0
1080; CHECK-NEXT:    i32.trunc_sat_f32_u
1081; CHECK-NEXT:    # fallthrough-return
1082entry:
1083  %conv = fptoui float %x to i64
1084  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
1085  %conv6 = trunc i64 %spec.store.select to i32
1086  ret i32 %conv6
1087}
1088
1089define i32 @ustest_f32i32_mm(float %x) {
1090; CHECK-LABEL: ustest_f32i32_mm:
1091; CHECK:         .functype ustest_f32i32_mm (f32) -> (i32)
1092; CHECK-NEXT:  # %bb.0: # %entry
1093; CHECK-NEXT:    local.get 0
1094; CHECK-NEXT:    i32.trunc_sat_f32_u
1095; CHECK-NEXT:    # fallthrough-return
1096entry:
1097  %conv = fptosi float %x to i64
1098  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
1099  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
1100  %conv6 = trunc i64 %spec.store.select7 to i32
1101  ret i32 %conv6
1102}
1103
1104define i32 @stest_f16i32_mm(half %x) {
1105; CHECK-LABEL: stest_f16i32_mm:
1106; CHECK:         .functype stest_f16i32_mm (f32) -> (i32)
1107; CHECK-NEXT:  # %bb.0: # %entry
1108; CHECK-NEXT:    local.get 0
1109; CHECK-NEXT:    call __truncsfhf2
1110; CHECK-NEXT:    call __extendhfsf2
1111; CHECK-NEXT:    i32.trunc_sat_f32_s
1112; CHECK-NEXT:    # fallthrough-return
1113entry:
1114  %conv = fptosi half %x to i64
1115  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
1116  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 -2147483648)
1117  %conv6 = trunc i64 %spec.store.select7 to i32
1118  ret i32 %conv6
1119}
1120
1121define i32 @utesth_f16i32_mm(half %x) {
1122; CHECK-LABEL: utesth_f16i32_mm:
1123; CHECK:         .functype utesth_f16i32_mm (f32) -> (i32)
1124; CHECK-NEXT:  # %bb.0: # %entry
1125; CHECK-NEXT:    local.get 0
1126; CHECK-NEXT:    call __truncsfhf2
1127; CHECK-NEXT:    call __extendhfsf2
1128; CHECK-NEXT:    i32.trunc_sat_f32_u
1129; CHECK-NEXT:    # fallthrough-return
1130entry:
1131  %conv = fptoui half %x to i64
1132  %spec.store.select = call i64 @llvm.umin.i64(i64 %conv, i64 4294967295)
1133  %conv6 = trunc i64 %spec.store.select to i32
1134  ret i32 %conv6
1135}
1136
1137define i32 @ustest_f16i32_mm(half %x) {
1138; CHECK-LABEL: ustest_f16i32_mm:
1139; CHECK:         .functype ustest_f16i32_mm (f32) -> (i32)
1140; CHECK-NEXT:  # %bb.0: # %entry
1141; CHECK-NEXT:    local.get 0
1142; CHECK-NEXT:    call __truncsfhf2
1143; CHECK-NEXT:    call __extendhfsf2
1144; CHECK-NEXT:    i32.trunc_sat_f32_u
1145; CHECK-NEXT:    # fallthrough-return
1146entry:
1147  %conv = fptosi half %x to i64
1148  %spec.store.select = call i64 @llvm.smin.i64(i64 %conv, i64 4294967295)
1149  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %spec.store.select, i64 0)
1150  %conv6 = trunc i64 %spec.store.select7 to i32
1151  ret i32 %conv6
1152}
1153
1154define i32 @ustest_f16i32_mm_cse(half %x) {
1155; CHECK-LABEL: ustest_f16i32_mm_cse:
1156; CHECK:         .functype ustest_f16i32_mm_cse (f32) -> (i32)
1157; CHECK-NEXT:  # %bb.0: # %entry
1158; CHECK-NEXT:    local.get 0
1159; CHECK-NEXT:    call __truncsfhf2
1160; CHECK-NEXT:    call __extendhfsf2
1161; CHECK-NEXT:    i32.trunc_sat_f32_u
1162; CHECK-NEXT:    # fallthrough-return
1163entry:
1164  %conv = fptosi half %x to i64
1165  %spec.store.select7 = call i64 @llvm.smax.i64(i64 %conv, i64 0)
1166  %conv6 = trunc i64 %spec.store.select7 to i32
1167  ret i32 %conv6
1168}
1169
1170; i16 saturate
1171
1172define i16 @stest_f64i16_mm(double %x) {
1173; CHECK-LABEL: stest_f64i16_mm:
1174; CHECK:         .functype stest_f64i16_mm (f64) -> (i32)
1175; CHECK-NEXT:    .local i32
1176; CHECK-NEXT:  # %bb.0: # %entry
1177; CHECK-NEXT:    local.get 0
1178; CHECK-NEXT:    i32.trunc_sat_f64_s
1179; CHECK-NEXT:    local.tee 1
1180; CHECK-NEXT:    i32.const 32767
1181; CHECK-NEXT:    local.get 1
1182; CHECK-NEXT:    i32.const 32767
1183; CHECK-NEXT:    i32.lt_s
1184; CHECK-NEXT:    i32.select
1185; CHECK-NEXT:    local.tee 1
1186; CHECK-NEXT:    i32.const -32768
1187; CHECK-NEXT:    local.get 1
1188; CHECK-NEXT:    i32.const -32768
1189; CHECK-NEXT:    i32.gt_s
1190; CHECK-NEXT:    i32.select
1191; CHECK-NEXT:    # fallthrough-return
1192entry:
1193  %conv = fptosi double %x to i32
1194  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
1195  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
1196  %conv6 = trunc i32 %spec.store.select7 to i16
1197  ret i16 %conv6
1198}
1199
1200define i16 @utest_f64i16_mm(double %x) {
1201; CHECK-LABEL: utest_f64i16_mm:
1202; CHECK:         .functype utest_f64i16_mm (f64) -> (i32)
1203; CHECK-NEXT:    .local i32
1204; CHECK-NEXT:  # %bb.0: # %entry
1205; CHECK-NEXT:    local.get 0
1206; CHECK-NEXT:    i32.trunc_sat_f64_u
1207; CHECK-NEXT:    local.tee 1
1208; CHECK-NEXT:    i32.const 65535
1209; CHECK-NEXT:    local.get 1
1210; CHECK-NEXT:    i32.const 65535
1211; CHECK-NEXT:    i32.lt_u
1212; CHECK-NEXT:    i32.select
1213; CHECK-NEXT:    # fallthrough-return
1214entry:
1215  %conv = fptoui double %x to i32
1216  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
1217  %conv6 = trunc i32 %spec.store.select to i16
1218  ret i16 %conv6
1219}
1220
1221define i16 @ustest_f64i16_mm(double %x) {
1222; CHECK-LABEL: ustest_f64i16_mm:
1223; CHECK:         .functype ustest_f64i16_mm (f64) -> (i32)
1224; CHECK-NEXT:    .local i32
1225; CHECK-NEXT:  # %bb.0: # %entry
1226; CHECK-NEXT:    local.get 0
1227; CHECK-NEXT:    i32.trunc_sat_f64_s
1228; CHECK-NEXT:    local.tee 1
1229; CHECK-NEXT:    i32.const 65535
1230; CHECK-NEXT:    local.get 1
1231; CHECK-NEXT:    i32.const 65535
1232; CHECK-NEXT:    i32.lt_s
1233; CHECK-NEXT:    i32.select
1234; CHECK-NEXT:    local.tee 1
1235; CHECK-NEXT:    i32.const 0
1236; CHECK-NEXT:    local.get 1
1237; CHECK-NEXT:    i32.const 0
1238; CHECK-NEXT:    i32.gt_s
1239; CHECK-NEXT:    i32.select
1240; CHECK-NEXT:    # fallthrough-return
1241entry:
1242  %conv = fptosi double %x to i32
1243  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
1244  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
1245  %conv6 = trunc i32 %spec.store.select7 to i16
1246  ret i16 %conv6
1247}
1248
1249define i16 @stest_f32i16_mm(float %x) {
1250; CHECK-LABEL: stest_f32i16_mm:
1251; CHECK:         .functype stest_f32i16_mm (f32) -> (i32)
1252; CHECK-NEXT:    .local i32
1253; CHECK-NEXT:  # %bb.0: # %entry
1254; CHECK-NEXT:    local.get 0
1255; CHECK-NEXT:    i32.trunc_sat_f32_s
1256; CHECK-NEXT:    local.tee 1
1257; CHECK-NEXT:    i32.const 32767
1258; CHECK-NEXT:    local.get 1
1259; CHECK-NEXT:    i32.const 32767
1260; CHECK-NEXT:    i32.lt_s
1261; CHECK-NEXT:    i32.select
1262; CHECK-NEXT:    local.tee 1
1263; CHECK-NEXT:    i32.const -32768
1264; CHECK-NEXT:    local.get 1
1265; CHECK-NEXT:    i32.const -32768
1266; CHECK-NEXT:    i32.gt_s
1267; CHECK-NEXT:    i32.select
1268; CHECK-NEXT:    # fallthrough-return
1269entry:
1270  %conv = fptosi float %x to i32
1271  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
1272  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
1273  %conv6 = trunc i32 %spec.store.select7 to i16
1274  ret i16 %conv6
1275}
1276
1277define i16 @utest_f32i16_mm(float %x) {
1278; CHECK-LABEL: utest_f32i16_mm:
1279; CHECK:         .functype utest_f32i16_mm (f32) -> (i32)
1280; CHECK-NEXT:    .local i32
1281; CHECK-NEXT:  # %bb.0: # %entry
1282; CHECK-NEXT:    local.get 0
1283; CHECK-NEXT:    i32.trunc_sat_f32_u
1284; CHECK-NEXT:    local.tee 1
1285; CHECK-NEXT:    i32.const 65535
1286; CHECK-NEXT:    local.get 1
1287; CHECK-NEXT:    i32.const 65535
1288; CHECK-NEXT:    i32.lt_u
1289; CHECK-NEXT:    i32.select
1290; CHECK-NEXT:    # fallthrough-return
1291entry:
1292  %conv = fptoui float %x to i32
1293  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
1294  %conv6 = trunc i32 %spec.store.select to i16
1295  ret i16 %conv6
1296}
1297
1298define i16 @ustest_f32i16_mm(float %x) {
1299; CHECK-LABEL: ustest_f32i16_mm:
1300; CHECK:         .functype ustest_f32i16_mm (f32) -> (i32)
1301; CHECK-NEXT:    .local i32
1302; CHECK-NEXT:  # %bb.0: # %entry
1303; CHECK-NEXT:    local.get 0
1304; CHECK-NEXT:    i32.trunc_sat_f32_s
1305; CHECK-NEXT:    local.tee 1
1306; CHECK-NEXT:    i32.const 65535
1307; CHECK-NEXT:    local.get 1
1308; CHECK-NEXT:    i32.const 65535
1309; CHECK-NEXT:    i32.lt_s
1310; CHECK-NEXT:    i32.select
1311; CHECK-NEXT:    local.tee 1
1312; CHECK-NEXT:    i32.const 0
1313; CHECK-NEXT:    local.get 1
1314; CHECK-NEXT:    i32.const 0
1315; CHECK-NEXT:    i32.gt_s
1316; CHECK-NEXT:    i32.select
1317; CHECK-NEXT:    # fallthrough-return
1318entry:
1319  %conv = fptosi float %x to i32
1320  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
1321  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
1322  %conv6 = trunc i32 %spec.store.select7 to i16
1323  ret i16 %conv6
1324}
1325
1326define i16 @stest_f16i16_mm(half %x) {
1327; CHECK-LABEL: stest_f16i16_mm:
1328; CHECK:         .functype stest_f16i16_mm (f32) -> (i32)
1329; CHECK-NEXT:    .local i32
1330; CHECK-NEXT:  # %bb.0: # %entry
1331; CHECK-NEXT:    local.get 0
1332; CHECK-NEXT:    call __truncsfhf2
1333; CHECK-NEXT:    call __extendhfsf2
1334; CHECK-NEXT:    i32.trunc_sat_f32_s
1335; CHECK-NEXT:    local.tee 1
1336; CHECK-NEXT:    i32.const 32767
1337; CHECK-NEXT:    local.get 1
1338; CHECK-NEXT:    i32.const 32767
1339; CHECK-NEXT:    i32.lt_s
1340; CHECK-NEXT:    i32.select
1341; CHECK-NEXT:    local.tee 1
1342; CHECK-NEXT:    i32.const -32768
1343; CHECK-NEXT:    local.get 1
1344; CHECK-NEXT:    i32.const -32768
1345; CHECK-NEXT:    i32.gt_s
1346; CHECK-NEXT:    i32.select
1347; CHECK-NEXT:    # fallthrough-return
1348entry:
1349  %conv = fptosi half %x to i32
1350  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
1351  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 -32768)
1352  %conv6 = trunc i32 %spec.store.select7 to i16
1353  ret i16 %conv6
1354}
1355
1356define i16 @utesth_f16i16_mm(half %x) {
1357; CHECK-LABEL: utesth_f16i16_mm:
1358; CHECK:         .functype utesth_f16i16_mm (f32) -> (i32)
1359; CHECK-NEXT:    .local i32
1360; CHECK-NEXT:  # %bb.0: # %entry
1361; CHECK-NEXT:    local.get 0
1362; CHECK-NEXT:    call __truncsfhf2
1363; CHECK-NEXT:    call __extendhfsf2
1364; CHECK-NEXT:    i32.trunc_sat_f32_u
1365; CHECK-NEXT:    local.tee 1
1366; CHECK-NEXT:    i32.const 65535
1367; CHECK-NEXT:    local.get 1
1368; CHECK-NEXT:    i32.const 65535
1369; CHECK-NEXT:    i32.lt_u
1370; CHECK-NEXT:    i32.select
1371; CHECK-NEXT:    # fallthrough-return
1372entry:
1373  %conv = fptoui half %x to i32
1374  %spec.store.select = call i32 @llvm.umin.i32(i32 %conv, i32 65535)
1375  %conv6 = trunc i32 %spec.store.select to i16
1376  ret i16 %conv6
1377}
1378
1379define i16 @ustest_f16i16_mm(half %x) {
1380; CHECK-LABEL: ustest_f16i16_mm:
1381; CHECK:         .functype ustest_f16i16_mm (f32) -> (i32)
1382; CHECK-NEXT:    .local i32
1383; CHECK-NEXT:  # %bb.0: # %entry
1384; CHECK-NEXT:    local.get 0
1385; CHECK-NEXT:    call __truncsfhf2
1386; CHECK-NEXT:    call __extendhfsf2
1387; CHECK-NEXT:    i32.trunc_sat_f32_s
1388; CHECK-NEXT:    local.tee 1
1389; CHECK-NEXT:    i32.const 65535
1390; CHECK-NEXT:    local.get 1
1391; CHECK-NEXT:    i32.const 65535
1392; CHECK-NEXT:    i32.lt_s
1393; CHECK-NEXT:    i32.select
1394; CHECK-NEXT:    local.tee 1
1395; CHECK-NEXT:    i32.const 0
1396; CHECK-NEXT:    local.get 1
1397; CHECK-NEXT:    i32.const 0
1398; CHECK-NEXT:    i32.gt_s
1399; CHECK-NEXT:    i32.select
1400; CHECK-NEXT:    # fallthrough-return
1401entry:
1402  %conv = fptosi half %x to i32
1403  %spec.store.select = call i32 @llvm.smin.i32(i32 %conv, i32 65535)
1404  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %spec.store.select, i32 0)
1405  %conv6 = trunc i32 %spec.store.select7 to i16
1406  ret i16 %conv6
1407}
1408
1409define i16 @ustest_f16i16_mm_cse(half %x) {
1410; CHECK-LABEL: ustest_f16i16_mm_cse:
1411; CHECK:         .functype ustest_f16i16_mm_cse (f32) -> (i32)
1412; CHECK-NEXT:  # %bb.0: # %entry
1413; CHECK-NEXT:    local.get 0
1414; CHECK-NEXT:    call __truncsfhf2
1415; CHECK-NEXT:    call __extendhfsf2
1416; CHECK-NEXT:    i32.trunc_sat_f32_u
1417; CHECK-NEXT:    # fallthrough-return
1418entry:
1419  %conv = fptosi half %x to i32
1420  %spec.store.select7 = call i32 @llvm.smax.i32(i32 %conv, i32 0)
1421  %conv6 = trunc i32 %spec.store.select7 to i16
1422  ret i16 %conv6
1423}
1424
1425; i64 saturate
1426
1427define i64 @stest_f64i64_mm(double %x) {
1428; CHECK-LABEL: stest_f64i64_mm:
1429; CHECK:         .functype stest_f64i64_mm (f64) -> (i64)
1430; CHECK-NEXT:  # %bb.0: # %entry
1431; CHECK-NEXT:    local.get 0
1432; CHECK-NEXT:    i64.trunc_sat_f64_s
1433; CHECK-NEXT:    # fallthrough-return
1434entry:
1435  %conv = fptosi double %x to i128
1436  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1437  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1438  %conv6 = trunc i128 %spec.store.select7 to i64
1439  ret i64 %conv6
1440}
1441
1442define i64 @utest_f64i64_mm(double %x) {
1443; CHECK-LABEL: utest_f64i64_mm:
1444; CHECK:         .functype utest_f64i64_mm (f64) -> (i64)
1445; CHECK-NEXT:    .local i32, i64, i64
1446; CHECK-NEXT:  # %bb.0: # %entry
1447; CHECK-NEXT:    global.get __stack_pointer
1448; CHECK-NEXT:    i32.const 16
1449; CHECK-NEXT:    i32.sub
1450; CHECK-NEXT:    local.tee 1
1451; CHECK-NEXT:    global.set __stack_pointer
1452; CHECK-NEXT:    local.get 1
1453; CHECK-NEXT:    local.get 0
1454; CHECK-NEXT:    call __fixunsdfti
1455; CHECK-NEXT:    local.get 1
1456; CHECK-NEXT:    i64.load 8
1457; CHECK-NEXT:    local.set 2
1458; CHECK-NEXT:    local.get 1
1459; CHECK-NEXT:    i64.load 0
1460; CHECK-NEXT:    local.set 3
1461; CHECK-NEXT:    local.get 1
1462; CHECK-NEXT:    i32.const 16
1463; CHECK-NEXT:    i32.add
1464; CHECK-NEXT:    global.set __stack_pointer
1465; CHECK-NEXT:    local.get 3
1466; CHECK-NEXT:    i64.const 0
1467; CHECK-NEXT:    local.get 2
1468; CHECK-NEXT:    i64.eqz
1469; CHECK-NEXT:    i64.select
1470; CHECK-NEXT:    # fallthrough-return
1471entry:
1472  %conv = fptoui double %x to i128
1473  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1474  %conv6 = trunc i128 %spec.store.select to i64
1475  ret i64 %conv6
1476}
1477
1478define i64 @ustest_f64i64_mm(double %x) {
1479; CHECK-LABEL: ustest_f64i64_mm:
1480; CHECK:         .functype ustest_f64i64_mm (f64) -> (i64)
1481; CHECK-NEXT:    .local i32, i64, i64
1482; CHECK-NEXT:  # %bb.0: # %entry
1483; CHECK-NEXT:    global.get __stack_pointer
1484; CHECK-NEXT:    i32.const 16
1485; CHECK-NEXT:    i32.sub
1486; CHECK-NEXT:    local.tee 1
1487; CHECK-NEXT:    global.set __stack_pointer
1488; CHECK-NEXT:    local.get 1
1489; CHECK-NEXT:    local.get 0
1490; CHECK-NEXT:    call __fixdfti
1491; CHECK-NEXT:    local.get 1
1492; CHECK-NEXT:    i64.load 8
1493; CHECK-NEXT:    local.set 2
1494; CHECK-NEXT:    local.get 1
1495; CHECK-NEXT:    i64.load 0
1496; CHECK-NEXT:    local.set 3
1497; CHECK-NEXT:    local.get 1
1498; CHECK-NEXT:    i32.const 16
1499; CHECK-NEXT:    i32.add
1500; CHECK-NEXT:    global.set __stack_pointer
1501; CHECK-NEXT:    i64.const 0
1502; CHECK-NEXT:    local.get 3
1503; CHECK-NEXT:    i64.const 0
1504; CHECK-NEXT:    local.get 2
1505; CHECK-NEXT:    i64.const 1
1506; CHECK-NEXT:    i64.lt_s
1507; CHECK-NEXT:    local.tee 1
1508; CHECK-NEXT:    i64.select
1509; CHECK-NEXT:    local.get 2
1510; CHECK-NEXT:    i64.const 1
1511; CHECK-NEXT:    local.get 1
1512; CHECK-NEXT:    i64.select
1513; CHECK-NEXT:    i64.const 0
1514; CHECK-NEXT:    i64.lt_s
1515; CHECK-NEXT:    i64.select
1516; CHECK-NEXT:    # fallthrough-return
1517entry:
1518  %conv = fptosi double %x to i128
1519  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1520  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1521  %conv6 = trunc i128 %spec.store.select7 to i64
1522  ret i64 %conv6
1523}
1524
1525define i64 @stest_f32i64_mm(float %x) {
1526; CHECK-LABEL: stest_f32i64_mm:
1527; CHECK:         .functype stest_f32i64_mm (f32) -> (i64)
1528; CHECK-NEXT:  # %bb.0: # %entry
1529; CHECK-NEXT:    local.get 0
1530; CHECK-NEXT:    i64.trunc_sat_f32_s
1531; CHECK-NEXT:    # fallthrough-return
1532entry:
1533  %conv = fptosi float %x to i128
1534  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1535  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1536  %conv6 = trunc i128 %spec.store.select7 to i64
1537  ret i64 %conv6
1538}
1539
1540define i64 @utest_f32i64_mm(float %x) {
1541; CHECK-LABEL: utest_f32i64_mm:
1542; CHECK:         .functype utest_f32i64_mm (f32) -> (i64)
1543; CHECK-NEXT:    .local i32, i64, i64
1544; CHECK-NEXT:  # %bb.0: # %entry
1545; CHECK-NEXT:    global.get __stack_pointer
1546; CHECK-NEXT:    i32.const 16
1547; CHECK-NEXT:    i32.sub
1548; CHECK-NEXT:    local.tee 1
1549; CHECK-NEXT:    global.set __stack_pointer
1550; CHECK-NEXT:    local.get 1
1551; CHECK-NEXT:    local.get 0
1552; CHECK-NEXT:    call __fixunssfti
1553; CHECK-NEXT:    local.get 1
1554; CHECK-NEXT:    i64.load 8
1555; CHECK-NEXT:    local.set 2
1556; CHECK-NEXT:    local.get 1
1557; CHECK-NEXT:    i64.load 0
1558; CHECK-NEXT:    local.set 3
1559; CHECK-NEXT:    local.get 1
1560; CHECK-NEXT:    i32.const 16
1561; CHECK-NEXT:    i32.add
1562; CHECK-NEXT:    global.set __stack_pointer
1563; CHECK-NEXT:    local.get 3
1564; CHECK-NEXT:    i64.const 0
1565; CHECK-NEXT:    local.get 2
1566; CHECK-NEXT:    i64.eqz
1567; CHECK-NEXT:    i64.select
1568; CHECK-NEXT:    # fallthrough-return
1569entry:
1570  %conv = fptoui float %x to i128
1571  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1572  %conv6 = trunc i128 %spec.store.select to i64
1573  ret i64 %conv6
1574}
1575
1576define i64 @ustest_f32i64_mm(float %x) {
1577; CHECK-LABEL: ustest_f32i64_mm:
1578; CHECK:         .functype ustest_f32i64_mm (f32) -> (i64)
1579; CHECK-NEXT:    .local i32, i64, i64
1580; CHECK-NEXT:  # %bb.0: # %entry
1581; CHECK-NEXT:    global.get __stack_pointer
1582; CHECK-NEXT:    i32.const 16
1583; CHECK-NEXT:    i32.sub
1584; CHECK-NEXT:    local.tee 1
1585; CHECK-NEXT:    global.set __stack_pointer
1586; CHECK-NEXT:    local.get 1
1587; CHECK-NEXT:    local.get 0
1588; CHECK-NEXT:    call __fixsfti
1589; CHECK-NEXT:    local.get 1
1590; CHECK-NEXT:    i64.load 8
1591; CHECK-NEXT:    local.set 2
1592; CHECK-NEXT:    local.get 1
1593; CHECK-NEXT:    i64.load 0
1594; CHECK-NEXT:    local.set 3
1595; CHECK-NEXT:    local.get 1
1596; CHECK-NEXT:    i32.const 16
1597; CHECK-NEXT:    i32.add
1598; CHECK-NEXT:    global.set __stack_pointer
1599; CHECK-NEXT:    i64.const 0
1600; CHECK-NEXT:    local.get 3
1601; CHECK-NEXT:    i64.const 0
1602; CHECK-NEXT:    local.get 2
1603; CHECK-NEXT:    i64.const 1
1604; CHECK-NEXT:    i64.lt_s
1605; CHECK-NEXT:    local.tee 1
1606; CHECK-NEXT:    i64.select
1607; CHECK-NEXT:    local.get 2
1608; CHECK-NEXT:    i64.const 1
1609; CHECK-NEXT:    local.get 1
1610; CHECK-NEXT:    i64.select
1611; CHECK-NEXT:    i64.const 0
1612; CHECK-NEXT:    i64.lt_s
1613; CHECK-NEXT:    i64.select
1614; CHECK-NEXT:    # fallthrough-return
1615entry:
1616  %conv = fptosi float %x to i128
1617  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1618  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1619  %conv6 = trunc i128 %spec.store.select7 to i64
1620  ret i64 %conv6
1621}
1622
1623define i64 @stest_f16i64_mm(half %x) {
1624; CHECK-LABEL: stest_f16i64_mm:
1625; CHECK:         .functype stest_f16i64_mm (f32) -> (i64)
1626; CHECK-NEXT:  # %bb.0: # %entry
1627; CHECK-NEXT:    local.get 0
1628; CHECK-NEXT:    call __truncsfhf2
1629; CHECK-NEXT:    call __extendhfsf2
1630; CHECK-NEXT:    i64.trunc_sat_f32_s
1631; CHECK-NEXT:    # fallthrough-return
1632entry:
1633  %conv = fptosi half %x to i128
1634  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 9223372036854775807)
1635  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 -9223372036854775808)
1636  %conv6 = trunc i128 %spec.store.select7 to i64
1637  ret i64 %conv6
1638}
1639
1640define i64 @utesth_f16i64_mm(half %x) {
1641; CHECK-LABEL: utesth_f16i64_mm:
1642; CHECK:         .functype utesth_f16i64_mm (f32) -> (i64)
1643; CHECK-NEXT:    .local i32, i64, i64
1644; CHECK-NEXT:  # %bb.0: # %entry
1645; CHECK-NEXT:    global.get __stack_pointer
1646; CHECK-NEXT:    i32.const 16
1647; CHECK-NEXT:    i32.sub
1648; CHECK-NEXT:    local.tee 1
1649; CHECK-NEXT:    global.set __stack_pointer
1650; CHECK-NEXT:    local.get 1
1651; CHECK-NEXT:    local.get 0
1652; CHECK-NEXT:    call __truncsfhf2
1653; CHECK-NEXT:    call __extendhfsf2
1654; CHECK-NEXT:    call __fixunssfti
1655; CHECK-NEXT:    local.get 1
1656; CHECK-NEXT:    i64.load 8
1657; CHECK-NEXT:    local.set 2
1658; CHECK-NEXT:    local.get 1
1659; CHECK-NEXT:    i64.load 0
1660; CHECK-NEXT:    local.set 3
1661; CHECK-NEXT:    local.get 1
1662; CHECK-NEXT:    i32.const 16
1663; CHECK-NEXT:    i32.add
1664; CHECK-NEXT:    global.set __stack_pointer
1665; CHECK-NEXT:    local.get 3
1666; CHECK-NEXT:    i64.const 0
1667; CHECK-NEXT:    local.get 2
1668; CHECK-NEXT:    i64.eqz
1669; CHECK-NEXT:    i64.select
1670; CHECK-NEXT:    # fallthrough-return
1671entry:
1672  %conv = fptoui half %x to i128
1673  %spec.store.select = call i128 @llvm.umin.i128(i128 %conv, i128 18446744073709551616)
1674  %conv6 = trunc i128 %spec.store.select to i64
1675  ret i64 %conv6
1676}
1677
1678define i64 @ustest_f16i64_mm(half %x) {
1679; CHECK-LABEL: ustest_f16i64_mm:
1680; CHECK:         .functype ustest_f16i64_mm (f32) -> (i64)
1681; CHECK-NEXT:    .local i32, i64, i64
1682; CHECK-NEXT:  # %bb.0: # %entry
1683; CHECK-NEXT:    global.get __stack_pointer
1684; CHECK-NEXT:    i32.const 16
1685; CHECK-NEXT:    i32.sub
1686; CHECK-NEXT:    local.tee 1
1687; CHECK-NEXT:    global.set __stack_pointer
1688; CHECK-NEXT:    local.get 1
1689; CHECK-NEXT:    local.get 0
1690; CHECK-NEXT:    call __truncsfhf2
1691; CHECK-NEXT:    call __extendhfsf2
1692; CHECK-NEXT:    call __fixsfti
1693; CHECK-NEXT:    local.get 1
1694; CHECK-NEXT:    i64.load 8
1695; CHECK-NEXT:    local.set 2
1696; CHECK-NEXT:    local.get 1
1697; CHECK-NEXT:    i64.load 0
1698; CHECK-NEXT:    local.set 3
1699; CHECK-NEXT:    local.get 1
1700; CHECK-NEXT:    i32.const 16
1701; CHECK-NEXT:    i32.add
1702; CHECK-NEXT:    global.set __stack_pointer
1703; CHECK-NEXT:    i64.const 0
1704; CHECK-NEXT:    local.get 3
1705; CHECK-NEXT:    i64.const 0
1706; CHECK-NEXT:    local.get 2
1707; CHECK-NEXT:    i64.const 1
1708; CHECK-NEXT:    i64.lt_s
1709; CHECK-NEXT:    local.tee 1
1710; CHECK-NEXT:    i64.select
1711; CHECK-NEXT:    local.get 2
1712; CHECK-NEXT:    i64.const 1
1713; CHECK-NEXT:    local.get 1
1714; CHECK-NEXT:    i64.select
1715; CHECK-NEXT:    i64.const 0
1716; CHECK-NEXT:    i64.lt_s
1717; CHECK-NEXT:    i64.select
1718; CHECK-NEXT:    # fallthrough-return
1719entry:
1720  %conv = fptosi half %x to i128
1721  %spec.store.select = call i128 @llvm.smin.i128(i128 %conv, i128 18446744073709551616)
1722  %spec.store.select7 = call i128 @llvm.smax.i128(i128 %spec.store.select, i128 0)
1723  %conv6 = trunc i128 %spec.store.select7 to i64
1724  ret i64 %conv6
1725}
1726
1727define i64 @utesth_f16i64_mm_cse(half %x) {
1728; CHECK-LABEL: utesth_f16i64_mm_cse:
1729; CHECK:         .functype utesth_f16i64_mm_cse (f32) -> (i64)
1730; CHECK-NEXT:    .local i32, i64
1731; CHECK-NEXT:  # %bb.0: # %entry
1732; CHECK-NEXT:    global.get __stack_pointer
1733; CHECK-NEXT:    i32.const 16
1734; CHECK-NEXT:    i32.sub
1735; CHECK-NEXT:    local.tee 1
1736; CHECK-NEXT:    global.set __stack_pointer
1737; CHECK-NEXT:    local.get 1
1738; CHECK-NEXT:    local.get 0
1739; CHECK-NEXT:    call __truncsfhf2
1740; CHECK-NEXT:    call __extendhfsf2
1741; CHECK-NEXT:    call __fixunssfti
1742; CHECK-NEXT:    local.get 1
1743; CHECK-NEXT:    i64.load 0
1744; CHECK-NEXT:    local.set 2
1745; CHECK-NEXT:    local.get 1
1746; CHECK-NEXT:    i32.const 16
1747; CHECK-NEXT:    i32.add
1748; CHECK-NEXT:    global.set __stack_pointer
1749; CHECK-NEXT:    local.get 2
1750; CHECK-NEXT:    # fallthrough-return
1751entry:
1752  %conv = fptoui half %x to i128
1753  %conv6 = trunc i128 %conv to i64
1754  ret i64 %conv6
1755}
1756
1757declare i32 @llvm.smin.i32(i32, i32)
1758declare i32 @llvm.smax.i32(i32, i32)
1759declare i32 @llvm.umin.i32(i32, i32)
1760declare i64 @llvm.smin.i64(i64, i64)
1761declare i64 @llvm.smax.i64(i64, i64)
1762declare i64 @llvm.umin.i64(i64, i64)
1763declare i128 @llvm.smin.i128(i128, i128)
1764declare i128 @llvm.smax.i128(i128, i128)
1765declare i128 @llvm.umin.i128(i128, i128)
1766