]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | //! Codegen `extern "platform-intrinsic"` intrinsics. |
2 | ||
3 | use super::*; | |
4 | use crate::prelude::*; | |
5 | ||
6 | pub(super) fn codegen_simd_intrinsic_call<'tcx>( | |
6a06907d | 7 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
29967ef6 XL |
8 | instance: Instance<'tcx>, |
9 | args: &[mir::Operand<'tcx>], | |
10 | ret: CPlace<'tcx>, | |
11 | span: Span, | |
12 | ) { | |
13 | let def_id = instance.def_id(); | |
14 | let substs = instance.substs; | |
15 | ||
17df50a5 | 16 | let intrinsic = fx.tcx.item_name(def_id); |
29967ef6 XL |
17 | |
18 | intrinsic_match! { | |
19 | fx, intrinsic, substs, args, | |
20 | _ => { | |
21 | fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); | |
22 | }; | |
23 | ||
24 | simd_cast, (c a) { | |
25 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
26 | simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| { | |
27 | let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap(); | |
28 | ||
29 | let from_signed = type_sign(lane_layout.ty); | |
30 | let to_signed = type_sign(ret_lane_layout.ty); | |
31 | ||
32 | let ret_lane = clif_int_or_float_cast(fx, lane, from_signed, ret_lane_ty, to_signed); | |
33 | CValue::by_val(ret_lane, ret_lane_layout) | |
34 | }); | |
35 | }; | |
36 | ||
29967ef6 XL |
37 | simd_eq, (c x, c y) { |
38 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 | 39 | simd_cmp!(fx, Equal|Equal(x, y) -> ret); |
29967ef6 XL |
40 | }; |
41 | simd_ne, (c x, c y) { | |
42 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 | 43 | simd_cmp!(fx, NotEqual|NotEqual(x, y) -> ret); |
29967ef6 XL |
44 | }; |
45 | simd_lt, (c x, c y) { | |
46 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 | 47 | simd_cmp!(fx, UnsignedLessThan|SignedLessThan|LessThan(x, y) -> ret); |
29967ef6 XL |
48 | }; |
49 | simd_le, (c x, c y) { | |
50 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 | 51 | simd_cmp!(fx, UnsignedLessThanOrEqual|SignedLessThanOrEqual|LessThanOrEqual(x, y) -> ret); |
29967ef6 XL |
52 | }; |
53 | simd_gt, (c x, c y) { | |
54 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 | 55 | simd_cmp!(fx, UnsignedGreaterThan|SignedGreaterThan|GreaterThan(x, y) -> ret); |
29967ef6 XL |
56 | }; |
57 | simd_ge, (c x, c y) { | |
58 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
fc512014 XL |
59 | simd_cmp!( |
60 | fx, | |
61 | UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual|GreaterThanOrEqual | |
62 | (x, y) -> ret | |
63 | ); | |
29967ef6 XL |
64 | }; |
65 | ||
66 | // simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U | |
17df50a5 | 67 | _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) { |
29967ef6 XL |
68 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); |
69 | ||
a2a8927a XL |
70 | // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. |
71 | // If there is no suffix, use the index array length. | |
72 | let n: u16 = if intrinsic == sym::simd_shuffle { | |
73 | // Make sure this is actually an array, since typeck only checks the length-suffixed | |
74 | // version of this intrinsic. | |
75 | let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); | |
76 | match idx_ty.kind() { | |
77 | ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { | |
78 | len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { | |
79 | span_bug!(span, "could not evaluate shuffle index array length") | |
80 | }).try_into().unwrap() | |
81 | } | |
82 | _ => { | |
83 | fx.tcx.sess.span_err( | |
84 | span, | |
85 | &format!( | |
86 | "simd_shuffle index must be an array of `u32`, got `{}`", | |
87 | idx_ty, | |
88 | ), | |
89 | ); | |
90 | // Prevent verifier error | |
91 | crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); | |
92 | return; | |
93 | } | |
94 | } | |
95 | } else { | |
96 | intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() | |
97 | }; | |
29967ef6 XL |
98 | |
99 | assert_eq!(x.layout(), y.layout()); | |
100 | let layout = x.layout(); | |
101 | ||
5869c6ff XL |
102 | let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); |
103 | let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); | |
29967ef6 | 104 | |
5869c6ff XL |
105 | assert_eq!(lane_ty, ret_lane_ty); |
106 | assert_eq!(u64::from(n), ret_lane_count); | |
29967ef6 XL |
107 | |
108 | let total_len = lane_count * 2; | |
109 | ||
110 | let indexes = { | |
111 | use rustc_middle::mir::interpret::*; | |
112 | let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const"); | |
113 | ||
6a06907d XL |
114 | let idx_bytes = match idx_const { |
115 | ConstValue::ByRef { alloc, offset } => { | |
cdc7bbd5 | 116 | let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */); |
17df50a5 | 117 | alloc.get_bytes(fx, alloc_range(offset, size)).unwrap() |
29967ef6 XL |
118 | } |
119 | _ => unreachable!("{:?}", idx_const), | |
120 | }; | |
121 | ||
122 | (0..ret_lane_count).map(|i| { | |
123 | let i = usize::try_from(i).unwrap(); | |
124 | let idx = rustc_middle::mir::interpret::read_target_uint( | |
125 | fx.tcx.data_layout.endian, | |
126 | &idx_bytes[4*i.. 4*i + 4], | |
127 | ).expect("read_target_uint"); | |
128 | u16::try_from(idx).expect("try_from u32") | |
129 | }).collect::<Vec<u16>>() | |
130 | }; | |
131 | ||
132 | for &idx in &indexes { | |
5869c6ff | 133 | assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len); |
29967ef6 XL |
134 | } |
135 | ||
136 | for (out_idx, in_idx) in indexes.into_iter().enumerate() { | |
5869c6ff | 137 | let in_lane = if u64::from(in_idx) < lane_count { |
94222f64 | 138 | x.value_lane(fx, in_idx.into()) |
29967ef6 | 139 | } else { |
94222f64 | 140 | y.value_lane(fx, u64::from(in_idx) - lane_count) |
29967ef6 | 141 | }; |
94222f64 | 142 | let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); |
29967ef6 XL |
143 | out_lane.write_cvalue(fx, in_lane); |
144 | } | |
145 | }; | |
146 | ||
147 | simd_insert, (c base, o idx, c val) { | |
148 | // FIXME validate | |
149 | let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { | |
150 | idx_const | |
151 | } else { | |
152 | fx.tcx.sess.span_fatal( | |
153 | span, | |
154 | "Index argument for `simd_insert` is not a constant", | |
155 | ); | |
156 | }; | |
157 | ||
6a06907d | 158 | let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); |
5869c6ff | 159 | let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx); |
29967ef6 XL |
160 | if idx >= lane_count.into() { |
161 | fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count)); | |
162 | } | |
163 | ||
164 | ret.write_cvalue(fx, base); | |
165 | let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap())); | |
166 | ret_lane.write_cvalue(fx, val); | |
167 | }; | |
168 | ||
169 | simd_extract, (c v, o idx) { | |
170 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
171 | let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { | |
172 | idx_const | |
173 | } else { | |
fc512014 | 174 | fx.tcx.sess.span_warn( |
29967ef6 XL |
175 | span, |
176 | "Index argument for `simd_extract` is not a constant", | |
177 | ); | |
fc512014 XL |
178 | let res = crate::trap::trap_unimplemented_ret_value( |
179 | fx, | |
180 | ret.layout(), | |
181 | "Index argument for `simd_extract` is not a constant", | |
182 | ); | |
183 | ret.write_cvalue(fx, res); | |
184 | return; | |
29967ef6 XL |
185 | }; |
186 | ||
6a06907d | 187 | let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); |
5869c6ff | 188 | let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx); |
29967ef6 XL |
189 | if idx >= lane_count.into() { |
190 | fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count)); | |
191 | } | |
192 | ||
94222f64 | 193 | let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); |
29967ef6 XL |
194 | ret.write_cvalue(fx, ret_lane); |
195 | }; | |
196 | ||
94222f64 XL |
197 | simd_neg, (c a) { |
198 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
199 | simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| { | |
200 | let ret_lane = match lane_layout.ty.kind() { | |
201 | ty::Int(_) => fx.bcx.ins().ineg(lane), | |
202 | ty::Float(_) => fx.bcx.ins().fneg(lane), | |
203 | _ => unreachable!(), | |
204 | }; | |
205 | CValue::by_val(ret_lane, ret_lane_layout) | |
206 | }); | |
207 | }; | |
208 | ||
209 | simd_fabs, (c a) { | |
210 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
211 | simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { | |
212 | let ret_lane = fx.bcx.ins().fabs(lane); | |
213 | CValue::by_val(ret_lane, ret_lane_layout) | |
214 | }); | |
215 | }; | |
216 | ||
217 | simd_fsqrt, (c a) { | |
218 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
219 | simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { | |
220 | let ret_lane = fx.bcx.ins().sqrt(lane); | |
221 | CValue::by_val(ret_lane, ret_lane_layout) | |
222 | }); | |
223 | }; | |
224 | ||
29967ef6 XL |
225 | simd_add, (c x, c y) { |
226 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
227 | simd_int_flt_binop!(fx, iadd|fadd(x, y) -> ret); | |
228 | }; | |
229 | simd_sub, (c x, c y) { | |
230 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
231 | simd_int_flt_binop!(fx, isub|fsub(x, y) -> ret); | |
232 | }; | |
233 | simd_mul, (c x, c y) { | |
234 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
235 | simd_int_flt_binop!(fx, imul|fmul(x, y) -> ret); | |
236 | }; | |
237 | simd_div, (c x, c y) { | |
238 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
239 | simd_int_flt_binop!(fx, udiv|sdiv|fdiv(x, y) -> ret); | |
240 | }; | |
94222f64 XL |
241 | simd_rem, (c x, c y) { |
242 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
243 | simd_pair_for_each_lane(fx, x, y, ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| { | |
244 | let res_lane = match lane_layout.ty.kind() { | |
245 | ty::Uint(_) => fx.bcx.ins().urem(x_lane, y_lane), | |
246 | ty::Int(_) => fx.bcx.ins().srem(x_lane, y_lane), | |
247 | ty::Float(FloatTy::F32) => fx.lib_call( | |
248 | "fmodf", | |
249 | vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], | |
250 | vec![AbiParam::new(types::F32)], | |
251 | &[x_lane, y_lane], | |
252 | )[0], | |
253 | ty::Float(FloatTy::F64) => fx.lib_call( | |
254 | "fmod", | |
255 | vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], | |
256 | vec![AbiParam::new(types::F64)], | |
257 | &[x_lane, y_lane], | |
258 | )[0], | |
259 | _ => unreachable!("{:?}", lane_layout.ty), | |
260 | }; | |
261 | CValue::by_val(res_lane, ret_lane_layout) | |
262 | }); | |
263 | }; | |
29967ef6 XL |
264 | simd_shl, (c x, c y) { |
265 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
266 | simd_int_binop!(fx, ishl(x, y) -> ret); | |
267 | }; | |
268 | simd_shr, (c x, c y) { | |
269 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
270 | simd_int_binop!(fx, ushr|sshr(x, y) -> ret); | |
271 | }; | |
272 | simd_and, (c x, c y) { | |
273 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
274 | simd_int_binop!(fx, band(x, y) -> ret); | |
275 | }; | |
276 | simd_or, (c x, c y) { | |
277 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
278 | simd_int_binop!(fx, bor(x, y) -> ret); | |
279 | }; | |
280 | simd_xor, (c x, c y) { | |
281 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
282 | simd_int_binop!(fx, bxor(x, y) -> ret); | |
283 | }; | |
284 | ||
285 | simd_fma, (c a, c b, c c) { | |
286 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
287 | assert_eq!(a.layout(), b.layout()); | |
288 | assert_eq!(a.layout(), c.layout()); | |
289 | let layout = a.layout(); | |
290 | ||
5869c6ff XL |
291 | let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx); |
292 | let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); | |
29967ef6 | 293 | assert_eq!(lane_count, ret_lane_count); |
5869c6ff | 294 | let ret_lane_layout = fx.layout_of(ret_lane_ty); |
29967ef6 XL |
295 | |
296 | for lane in 0..lane_count { | |
94222f64 XL |
297 | let a_lane = a.value_lane(fx, lane).load_scalar(fx); |
298 | let b_lane = b.value_lane(fx, lane).load_scalar(fx); | |
299 | let c_lane = c.value_lane(fx, lane).load_scalar(fx); | |
29967ef6 XL |
300 | |
301 | let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane); | |
302 | let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout); | |
303 | ||
94222f64 | 304 | ret.place_lane(fx, lane).write_cvalue(fx, res_lane); |
29967ef6 XL |
305 | } |
306 | }; | |
307 | ||
308 | simd_fmin, (c x, c y) { | |
309 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
310 | simd_flt_binop!(fx, fmin(x, y) -> ret); | |
311 | }; | |
312 | simd_fmax, (c x, c y) { | |
313 | validate_simd_type!(fx, intrinsic, span, x.layout().ty); | |
314 | simd_flt_binop!(fx, fmax(x, y) -> ret); | |
315 | }; | |
316 | ||
94222f64 XL |
317 | simd_round, (c a) { |
318 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
319 | simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| { | |
320 | let res_lane = match lane_layout.ty.kind() { | |
321 | ty::Float(FloatTy::F32) => fx.lib_call( | |
322 | "roundf", | |
323 | vec![AbiParam::new(types::F32)], | |
324 | vec![AbiParam::new(types::F32)], | |
325 | &[lane], | |
326 | )[0], | |
327 | ty::Float(FloatTy::F64) => fx.lib_call( | |
328 | "round", | |
329 | vec![AbiParam::new(types::F64)], | |
330 | vec![AbiParam::new(types::F64)], | |
331 | &[lane], | |
332 | )[0], | |
333 | _ => unreachable!("{:?}", lane_layout.ty), | |
334 | }; | |
335 | CValue::by_val(res_lane, ret_lane_layout) | |
336 | }); | |
337 | }; | |
338 | simd_ceil, (c a) { | |
339 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
340 | simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { | |
341 | let ret_lane = fx.bcx.ins().ceil(lane); | |
342 | CValue::by_val(ret_lane, ret_lane_layout) | |
343 | }); | |
344 | }; | |
345 | simd_floor, (c a) { | |
346 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
347 | simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { | |
348 | let ret_lane = fx.bcx.ins().floor(lane); | |
349 | CValue::by_val(ret_lane, ret_lane_layout) | |
350 | }); | |
351 | }; | |
352 | simd_trunc, (c a) { | |
353 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
354 | simd_for_each_lane(fx, a, ret, |fx, _lane_layout, ret_lane_layout, lane| { | |
355 | let ret_lane = fx.bcx.ins().trunc(lane); | |
356 | CValue::by_val(ret_lane, ret_lane_layout) | |
357 | }); | |
358 | }; | |
359 | ||
360 | simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) { | |
fc512014 | 361 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); |
94222f64 | 362 | simd_reduce(fx, v, Some(acc), ret, |fx, lane_layout, a, b| { |
fc512014 XL |
363 | if lane_layout.ty.is_floating_point() { |
364 | fx.bcx.ins().fadd(a, b) | |
365 | } else { | |
366 | fx.bcx.ins().iadd(a, b) | |
367 | } | |
368 | }); | |
369 | }; | |
370 | ||
94222f64 | 371 | simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v, v acc) { |
fc512014 | 372 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); |
94222f64 | 373 | simd_reduce(fx, v, Some(acc), ret, |fx, lane_layout, a, b| { |
fc512014 XL |
374 | if lane_layout.ty.is_floating_point() { |
375 | fx.bcx.ins().fmul(a, b) | |
376 | } else { | |
377 | fx.bcx.ins().imul(a, b) | |
378 | } | |
379 | }); | |
380 | }; | |
381 | ||
382 | simd_reduce_all, (c v) { | |
383 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
384 | simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().band(a, b)); | |
385 | }; | |
386 | ||
387 | simd_reduce_any, (c v) { | |
388 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
389 | simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().bor(a, b)); | |
390 | }; | |
391 | ||
94222f64 XL |
392 | simd_reduce_and, (c v) { |
393 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
394 | simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().band(a, b)); | |
395 | }; | |
396 | ||
397 | simd_reduce_or, (c v) { | |
398 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
399 | simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().bor(a, b)); | |
400 | }; | |
401 | ||
402 | simd_reduce_xor, (c v) { | |
403 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); | |
404 | simd_reduce(fx, v, None, ret, |fx, _layout, a, b| fx.bcx.ins().bxor(a, b)); | |
405 | }; | |
406 | ||
407 | simd_reduce_min, (c v) { | |
94222f64 XL |
408 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); |
409 | simd_reduce(fx, v, None, ret, |fx, layout, a, b| { | |
a2a8927a XL |
410 | let lt = match layout.ty.kind() { |
411 | ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b), | |
412 | ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b), | |
413 | ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b), | |
414 | _ => unreachable!(), | |
415 | }; | |
94222f64 XL |
416 | fx.bcx.ins().select(lt, a, b) |
417 | }); | |
418 | }; | |
419 | ||
420 | simd_reduce_max, (c v) { | |
94222f64 XL |
421 | validate_simd_type!(fx, intrinsic, span, v.layout().ty); |
422 | simd_reduce(fx, v, None, ret, |fx, layout, a, b| { | |
a2a8927a XL |
423 | let gt = match layout.ty.kind() { |
424 | ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b), | |
425 | ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b), | |
426 | ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b), | |
427 | _ => unreachable!(), | |
428 | }; | |
94222f64 XL |
429 | fx.bcx.ins().select(gt, a, b) |
430 | }); | |
431 | }; | |
432 | ||
433 | simd_select, (c m, c a, c b) { | |
434 | validate_simd_type!(fx, intrinsic, span, m.layout().ty); | |
435 | validate_simd_type!(fx, intrinsic, span, a.layout().ty); | |
436 | assert_eq!(a.layout(), b.layout()); | |
437 | ||
438 | let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); | |
439 | let lane_layout = fx.layout_of(lane_ty); | |
440 | ||
441 | for lane in 0..lane_count { | |
442 | let m_lane = m.value_lane(fx, lane).load_scalar(fx); | |
443 | let a_lane = a.value_lane(fx, lane).load_scalar(fx); | |
444 | let b_lane = b.value_lane(fx, lane).load_scalar(fx); | |
445 | ||
446 | let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0); | |
447 | let res_lane = CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); | |
448 | ||
449 | ret.place_lane(fx, lane).write_cvalue(fx, res_lane); | |
450 | } | |
451 | }; | |
452 | ||
453 | // simd_saturating_* | |
29967ef6 | 454 | // simd_bitmask |
94222f64 XL |
455 | // simd_scatter |
456 | // simd_gather | |
29967ef6 XL |
457 | } |
458 | } |