llvm.org GIT mirror llvm / ca6f7dc
[WebAssembly] Saturating float to int intrinsics Summary: Although the saturating float to int instructions are already emitted from normal IR, the fpto{s,u}i instructions produce poison values if the argument cannot fit in the result type. These intrinsics are therefore necessary to get guaranteed defined saturating behavior. Reviewers: aheejin, dschuff Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D53004 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344204 91177308-0d34-0410-b5e6-96231b3b80d8 Thomas Lively 1 year, 5 months ago
5 changed file(s) with 175 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
3434 // These are the old old names. They also lack the immediate field.
3535 def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
3636 def int_wasm_grow_memory : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], []>;
37
38 //===----------------------------------------------------------------------===//
39 // Saturating float-to-int conversions
40 //===----------------------------------------------------------------------===//
41
42 def int_wasm_trunc_saturate_signed : Intrinsic<[llvm_anyint_ty],
43 [llvm_anyfloat_ty],
44 [IntrNoMem, IntrSpeculatable]>;
45 def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty],
46 [llvm_anyfloat_ty],
47 [IntrNoMem, IntrSpeculatable]>;
3748
3849 //===----------------------------------------------------------------------===//
3950 // Exception handling intrinsics
9595 "i64.trunc_u:sat/f64\t$dst, $src",
9696 "i64.trunc_u:sat/f64", 0xfc07>,
9797 Requires<[HasNontrappingFPToInt]>;
98
99 // Lower llvm.wasm.trunc.saturate.* to saturating instructions
100 def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
101 (I32_TRUNC_S_SAT_F32 F32:$src)>;
102 def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
103 (I32_TRUNC_U_SAT_F32 F32:$src)>;
104 def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
105 (I32_TRUNC_S_SAT_F64 F64:$src)>;
106 def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
107 (I32_TRUNC_U_SAT_F64 F64:$src)>;
108 def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
109 (I64_TRUNC_S_SAT_F32 F32:$src)>;
110 def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
111 (I64_TRUNC_U_SAT_F32 F32:$src)>;
112 def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
113 (I64_TRUNC_S_SAT_F64 F64:$src)>;
114 def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
115 (I64_TRUNC_U_SAT_F64 F64:$src)>;
98116
99117 // Conversion from floating point to integer pseudo-instructions which don't
100118 // trap on overflow or invalid.
781781 defm "" : SIMDConvert;
782782 defm "" : SIMDConvert;
783783
784 // Lower llvm.wasm.trunc.saturate.* to saturating instructions
785 def : Pat<(v4i32 (int_wasm_trunc_saturate_signed (v4f32 V128:$src))),
786 (fp_to_sint_v4i32_v4f32 (v4f32 V128:$src))>;
787 def : Pat<(v4i32 (int_wasm_trunc_saturate_unsigned (v4f32 V128:$src))),
788 (fp_to_uint_v4i32_v4f32 (v4f32 V128:$src))>;
789 def : Pat<(v2i64 (int_wasm_trunc_saturate_signed (v2f64 V128:$src))),
790 (fp_to_sint_v2i64_v2f64 (v2f64 V128:$src))>;
791 def : Pat<(v2i64 (int_wasm_trunc_saturate_unsigned (v2f64 V128:$src))),
792 (fp_to_uint_v2i64_v2f64 (v2f64 V128:$src))>;
793
784794 // Bitcasts are nops
785795 // Matching bitcast t1 to t1 causes strange errors, so avoid repeating types
786796 foreach t1 = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in
4444 ret i32 %a
4545 }
4646
47 ; CHECK-LABEL: i32_trunc_sat_s_f32:
48 ; CHECK-NEXT: .param f32{{$}}
49 ; CHECK-NEXT: .result i32{{$}}
50 ; CHECK-NEXT: i32.trunc_s:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
51 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
52 declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
53 define i32 @i32_trunc_sat_s_f32(float %x) {
54 %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %x)
55 ret i32 %a
56 }
57
4758 ; CHECK-LABEL: i32_trunc_u_f32:
4859 ; CHECK-NEXT: .param f32{{$}}
4960 ; CHECK-NEXT: .result i32{{$}}
5465 ret i32 %a
5566 }
5667
68 ; CHECK-LABEL: i32_trunc_sat_u_f32:
69 ; CHECK-NEXT: .param f32{{$}}
70 ; CHECK-NEXT: .result i32{{$}}
71 ; CHECK-NEXT: i32.trunc_u:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
72 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
73 declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
74 define i32 @i32_trunc_sat_u_f32(float %x) {
75 %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %x)
76 ret i32 %a
77 }
78
5779 ; CHECK-LABEL: i32_trunc_s_f64:
5880 ; CHECK-NEXT: .param f64{{$}}
5981 ; CHECK-NEXT: .result i32{{$}}
6486 ret i32 %a
6587 }
6688
89 ; CHECK-LABEL: i32_trunc_sat_s_f64:
90 ; CHECK-NEXT: .param f64{{$}}
91 ; CHECK-NEXT: .result i32{{$}}
92 ; CHECK-NEXT: i32.trunc_s:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
93 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
94 declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
95 define i32 @i32_trunc_sat_s_f64(double %x) {
96 %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %x)
97 ret i32 %a
98 }
99
67100 ; CHECK-LABEL: i32_trunc_u_f64:
68101 ; CHECK-NEXT: .param f64{{$}}
69102 ; CHECK-NEXT: .result i32{{$}}
74107 ret i32 %a
75108 }
76109
110 ; CHECK-LABEL: i32_trunc_sat_u_f64:
111 ; CHECK-NEXT: .param f64{{$}}
112 ; CHECK-NEXT: .result i32{{$}}
113 ; CHECK-NEXT: i32.trunc_u:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
114 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
115 declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
116 define i32 @i32_trunc_sat_u_f64(double %x) {
117 %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %x)
118 ret i32 %a
119 }
120
77121 ; CHECK-LABEL: i64_trunc_s_f32:
78122 ; CHECK-NEXT: .param f32{{$}}
79123 ; CHECK-NEXT: .result i64{{$}}
84128 ret i64 %a
85129 }
86130
131 ; CHECK-LABEL: i64_trunc_sat_s_f32:
132 ; CHECK-NEXT: .param f32{{$}}
133 ; CHECK-NEXT: .result i64{{$}}
134 ; CHECK-NEXT: i64.trunc_s:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
135 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
136 declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
137 define i64 @i64_trunc_sat_s_f32(float %x) {
138 %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %x)
139 ret i64 %a
140 }
141
87142 ; CHECK-LABEL: i64_trunc_u_f32:
88143 ; CHECK-NEXT: .param f32{{$}}
89144 ; CHECK-NEXT: .result i64{{$}}
94149 ret i64 %a
95150 }
96151
152 ; CHECK-LABEL: i64_trunc_sat_u_f32:
153 ; CHECK-NEXT: .param f32{{$}}
154 ; CHECK-NEXT: .result i64{{$}}
155 ; CHECK-NEXT: i64.trunc_u:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
156 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
157 declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
158 define i64 @i64_trunc_sat_u_f32(float %x) {
159 %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %x)
160 ret i64 %a
161 }
162
97163 ; CHECK-LABEL: i64_trunc_s_f64:
98164 ; CHECK-NEXT: .param f64{{$}}
99165 ; CHECK-NEXT: .result i64{{$}}
104170 ret i64 %a
105171 }
106172
173 ; CHECK-LABEL: i64_trunc_sat_s_f64:
174 ; CHECK-NEXT: .param f64{{$}}
175 ; CHECK-NEXT: .result i64{{$}}
176 ; CHECK-NEXT: i64.trunc_s:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
177 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
178 declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
179 define i64 @i64_trunc_sat_s_f64(double %x) {
180 %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %x)
181 ret i64 %a
182 }
183
107184 ; CHECK-LABEL: i64_trunc_u_f64:
108185 ; CHECK-NEXT: .param f64{{$}}
109186 ; CHECK-NEXT: .result i64{{$}}
111188 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
112189 define i64 @i64_trunc_u_f64(double %x) {
113190 %a = fptoui double %x to i64
191 ret i64 %a
192 }
193
194 ; CHECK-LABEL: i64_trunc_sat_u_f64:
195 ; CHECK-NEXT: .param f64{{$}}
196 ; CHECK-NEXT: .result i64{{$}}
197 ; CHECK-NEXT: i64.trunc_u:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
198 ; CHECK-NEXT: return $pop[[NUM]]{{$}}
199 declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
200 define i64 @i64_trunc_sat_u_f64(double %x) {
201 %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %x)
114202 ret i64 %a
115203 }
116204
225225 ret <4 x i32> %a
226226 }
227227
228 ; CHECK-LABEL: trunc_sat_s_v4i32:
229 ; NO-SIMD128-NOT: f32x4
230 ; SIMD128-NEXT: .param v128{{$}}
231 ; SIMD128-NEXT: .result v128{{$}}
232 ; SIMD128-NEXT: i32x4.trunc_sat_s/f32x4 $push[[R:[0-9]+]]=, $0
233 ; SIMD128-NEXT: return $pop[[R]]
234 declare <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float>)
235 define <4 x i32> @trunc_sat_s_v4i32(<4 x float> %x) {
236 %a = call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %x)
237 ret <4 x i32> %a
238 }
239
240 ; CHECK-LABEL: trunc_sat_u_v4i32:
241 ; NO-SIMD128-NOT: f32x4
242 ; SIMD128-NEXT: .param v128{{$}}
243 ; SIMD128-NEXT: .result v128{{$}}
244 ; SIMD128-NEXT: i32x4.trunc_sat_u/f32x4 $push[[R:[0-9]+]]=, $0
245 ; SIMD128-NEXT: return $pop[[R]]
246 declare <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float>)
247 define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) {
248 %a = call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %x)
249 ret <4 x i32> %a
250 }
251
228252 ; ==============================================================================
229253 ; 2 x i64
230254 ; ==============================================================================
263287 ret <2 x i64> %a
264288 }
265289
290 ; CHECK-LABEL: trunc_sat_s_v2i64:
291 ; NO-SIMD128-NOT: f32x4
292 ; SIMD128-NEXT: .param v128{{$}}
293 ; SIMD128-NEXT: .result v128{{$}}
294 ; SIMD128-NEXT: i64x2.trunc_sat_s/f64x2 $push[[R:[0-9]+]]=, $0
295 ; SIMD128-NEXT: return $pop[[R]]
296 declare <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double>)
297 define <2 x i64> @trunc_sat_s_v2i64(<2 x double> %x) {
298 %a = call <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double> %x)
299 ret <2 x i64> %a
300 }
301
302 ; CHECK-LABEL: trunc_sat_u_v2i64:
303 ; NO-SIMD128-NOT: f32x4
304 ; SIMD128-NEXT: .param v128{{$}}
305 ; SIMD128-NEXT: .result v128{{$}}
306 ; SIMD128-NEXT: i64x2.trunc_sat_u/f64x2 $push[[R:[0-9]+]]=, $0
307 ; SIMD128-NEXT: return $pop[[R]]
308 declare <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double>)
309 define <2 x i64> @trunc_sat_u_v2i64(<2 x double> %x) {
310 %a = call <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double> %x)
311 ret <2 x i64> %a
312 }
313
266314 ; ==============================================================================
267315 ; 4 x f32
268316 ; ==============================================================================