1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s
2
3; Test that basic conversion operations assemble as expected using
4; the trapping opcodes and explicit code to suppress the trapping.
5
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
9; CHECK-LABEL: i32_trunc_s_f32:
10; CHECK-NEXT: .functype i32_trunc_s_f32 (f32) -> (i32){{$}}
11; CHECK-NEXT: block
12; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
13; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
14; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
15; CHECK-NEXT: br_if 0, $pop[[LT]]{{$}}
16; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
17; CHECK-NEXT: return $pop[[ALT]]{{$}}
18; CHECK-NEXT: BB
19; CHECK-NEXT: end_block
20; CHECK-NEXT: i32.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
21; CHECK-NEXT: return $pop[[NUM]]{{$}}
22define i32 @i32_trunc_s_f32(float %x) {
23  %a = fptosi float %x to i32
24  ret i32 %a
25}
26
27; CHECK-LABEL: i32_trunc_u_f32:
28; CHECK-NEXT: .functype i32_trunc_u_f32 (f32) -> (i32){{$}}
29; CHECK-NEXT: block
30; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
31; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
32; CHECK-NEXT: f32.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
33; CHECK-NEXT: f32.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
34; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
35; CHECK-NEXT: br_if 0, $pop[[AND]]{{$}}
36; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
37; CHECK-NEXT: return $pop[[ALT]]{{$}}
38; CHECK-NEXT: BB
39; CHECK-NEXT: end_block
40; CHECK-NEXT: i32.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
41; CHECK-NEXT: return $pop[[NUM]]{{$}}
42define i32 @i32_trunc_u_f32(float %x) {
43  %a = fptoui float %x to i32
44  ret i32 %a
45}
46
47; CHECK-LABEL: i32_trunc_s_f64:
48; CHECK-NEXT: .functype i32_trunc_s_f64 (f64) -> (i32){{$}}
49; CHECK-NEXT: block
50; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
51; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
52; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
53; CHECK-NEXT: br_if 0, $pop[[LT]]{{$}}
54; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
55; CHECK-NEXT: return $pop[[ALT]]{{$}}
56; CHECK-NEXT: BB
57; CHECK-NEXT: end_block
58; CHECK-NEXT: i32.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
59; CHECK-NEXT: return $pop[[NUM]]{{$}}
60define i32 @i32_trunc_s_f64(double %x) {
61  %a = fptosi double %x to i32
62  ret i32 %a
63}
64
65; CHECK-LABEL: i32_trunc_u_f64:
66; CHECK-NEXT: .functype i32_trunc_u_f64 (f64) -> (i32){{$}}
67; CHECK-NEXT: block
68; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
69; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
70; CHECK-NEXT: f64.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
71; CHECK-NEXT: f64.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
72; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
73; CHECK-NEXT: br_if 0, $pop[[AND]]{{$}}
74; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
75; CHECK-NEXT: return $pop[[ALT]]{{$}}
76; CHECK-NEXT: BB
77; CHECK-NEXT: end_block
78; CHECK-NEXT: i32.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
79; CHECK-NEXT: return $pop[[NUM]]{{$}}
80define i32 @i32_trunc_u_f64(double %x) {
81  %a = fptoui double %x to i32
82  ret i32 %a
83}
84
85; CHECK-LABEL: i64_trunc_s_f32:
86; CHECK-NEXT: .functype i64_trunc_s_f32 (f32) -> (i64){{$}}
87; CHECK-NEXT: block
88; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
89; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
90; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
91; CHECK-NEXT: br_if 0, $pop[[LT]]{{$}}
92; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
93; CHECK-NEXT: return $pop[[ALT]]{{$}}
94; CHECK-NEXT: BB
95; CHECK-NEXT: end_block
96; CHECK-NEXT: i64.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
97; CHECK-NEXT: return $pop[[NUM]]{{$}}
98define i64 @i64_trunc_s_f32(float %x) {
99  %a = fptosi float %x to i64
100  ret i64 %a
101}
102
103; CHECK-LABEL: i64_trunc_u_f32:
104; CHECK-NEXT: .functype i64_trunc_u_f32 (f32) -> (i64){{$}}
105; CHECK-NEXT: block
106; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
107; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
108; CHECK-NEXT: f32.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
109; CHECK-NEXT: f32.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
110; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
111; CHECK-NEXT: br_if 0, $pop[[AND]]{{$}}
112; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
113; CHECK-NEXT: return $pop[[ALT]]{{$}}
114; CHECK-NEXT: BB
115; CHECK-NEXT: end_block
116; CHECK-NEXT: i64.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
117; CHECK-NEXT: return $pop[[NUM]]{{$}}
118define i64 @i64_trunc_u_f32(float %x) {
119  %a = fptoui float %x to i64
120  ret i64 %a
121}
122
123; CHECK-LABEL: i64_trunc_s_f64:
124; CHECK-NEXT: .functype i64_trunc_s_f64 (f64) -> (i64){{$}}
125; CHECK-NEXT: block
126; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
127; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
128; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
129; CHECK-NEXT: br_if 0, $pop[[LT]]{{$}}
130; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
131; CHECK-NEXT: return $pop[[ALT]]{{$}}
132; CHECK-NEXT: BB
133; CHECK-NEXT: end_block
134; CHECK-NEXT: i64.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
135; CHECK-NEXT: return $pop[[NUM]]{{$}}
136define i64 @i64_trunc_s_f64(double %x) {
137  %a = fptosi double %x to i64
138  ret i64 %a
139}
140
141; CHECK-LABEL: i64_trunc_u_f64:
142; CHECK-NEXT: .functype i64_trunc_u_f64 (f64) -> (i64){{$}}
143; CHECK-NEXT: block
144; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
145; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
146; CHECK-NEXT: f64.const $push[[ZERO:[0-9]+]]=, 0x0p0{{$}}
147; CHECK-NEXT: f64.ge $push[[GE:[0-9]+]]=, $0, $pop[[ZERO]]{{$}}
148; CHECK-NEXT: i32.and $push[[AND:[0-9]+]]=, $pop[[LT]], $pop[[GE]]{{$}}
149; CHECK-NEXT: br_if 0, $pop[[AND]]{{$}}
150; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
151; CHECK-NEXT: return $pop[[ALT]]{{$}}
152; CHECK-NEXT: BB
153; CHECK-NEXT: end_block
154; CHECK-NEXT: i64.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
155; CHECK-NEXT: return $pop[[NUM]]{{$}}
156define i64 @i64_trunc_u_f64(double %x) {
157  %a = fptoui double %x to i64
158  ret i64 %a
159}
160