|
1 | | -use rustc_apfloat::{ |
2 | | - ieee::{Double, Single}, |
3 | | - Float as _, |
4 | | -}; |
5 | | -use rustc_middle::mir; |
| 1 | +use rustc_apfloat::ieee::Double; |
6 | 2 | use rustc_middle::ty::layout::LayoutOf as _; |
7 | 3 | use rustc_middle::ty::Ty; |
8 | 4 | use rustc_span::Symbol; |
@@ -39,49 +35,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: |
39 | 35 | // Intrinsincs sufixed with "epiX" or "epuX" operate with X-bit signed or unsigned |
40 | 36 | // vectors. |
41 | 37 | match unprefixed_name { |
42 | | - // Used to implement the _mm_avg_epu8 and _mm_avg_epu16 functions. |
43 | | - // Averages packed unsigned 8/16-bit integers in `left` and `right`. |
44 | | - "pavg.b" | "pavg.w" => { |
45 | | - let [left, right] = |
46 | | - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
47 | | - |
48 | | - let (left, left_len) = this.operand_to_simd(left)?; |
49 | | - let (right, right_len) = this.operand_to_simd(right)?; |
50 | | - let (dest, dest_len) = this.place_to_simd(dest)?; |
51 | | - |
52 | | - assert_eq!(dest_len, left_len); |
53 | | - assert_eq!(dest_len, right_len); |
54 | | - |
55 | | - for i in 0..dest_len { |
56 | | - let left = this.read_immediate(&this.project_index(&left, i)?)?; |
57 | | - let right = this.read_immediate(&this.project_index(&right, i)?)?; |
58 | | - let dest = this.project_index(&dest, i)?; |
59 | | - |
60 | | - // Widen the operands to avoid overflow |
61 | | - let twice_wide = this.layout_of(this.get_twice_wide_int_ty(left.layout.ty))?; |
62 | | - let left = this.int_to_int_or_float(&left, twice_wide)?; |
63 | | - let right = this.int_to_int_or_float(&right, twice_wide)?; |
64 | | - |
65 | | - // Calculate left + right + 1 |
66 | | - let added = this.wrapping_binary_op(mir::BinOp::Add, &left, &right)?; |
67 | | - let added = this.wrapping_binary_op( |
68 | | - mir::BinOp::Add, |
69 | | - &added, |
70 | | - &ImmTy::from_uint(1u32, twice_wide), |
71 | | - )?; |
72 | | - |
73 | | - // Calculate (left + right + 1) / 2 |
74 | | - let divided = this.wrapping_binary_op( |
75 | | - mir::BinOp::Div, |
76 | | - &added, |
77 | | - &ImmTy::from_uint(2u32, twice_wide), |
78 | | - )?; |
79 | | - |
80 | | - // Narrow back to the original type |
81 | | - let res = this.int_to_int_or_float(÷d, dest.layout)?; |
82 | | - this.write_immediate(*res, &dest)?; |
83 | | - } |
84 | | - } |
85 | 38 | // Used to implement the _mm_madd_epi16 function. |
86 | 39 | // Multiplies packed signed 16-bit integers in `left` and `right`, producing |
87 | 40 | // intermediate signed 32-bit integers. Horizontally add adjacent pairs of |
@@ -118,70 +71,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: |
118 | 71 | this.write_scalar(Scalar::from_i32(res), &dest)?; |
119 | 72 | } |
120 | 73 | } |
121 | | - // Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions. |
122 | | - "pmulh.w" | "pmulhu.w" => { |
123 | | - let [left, right] = |
124 | | - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
125 | | - |
126 | | - let (left, left_len) = this.operand_to_simd(left)?; |
127 | | - let (right, right_len) = this.operand_to_simd(right)?; |
128 | | - let (dest, dest_len) = this.place_to_simd(dest)?; |
129 | | - |
130 | | - assert_eq!(dest_len, left_len); |
131 | | - assert_eq!(dest_len, right_len); |
132 | | - |
133 | | - for i in 0..dest_len { |
134 | | - let left = this.read_immediate(&this.project_index(&left, i)?)?; |
135 | | - let right = this.read_immediate(&this.project_index(&right, i)?)?; |
136 | | - let dest = this.project_index(&dest, i)?; |
137 | | - |
138 | | - // Widen the operands to avoid overflow |
139 | | - let twice_wide = this.layout_of(this.get_twice_wide_int_ty(left.layout.ty))?; |
140 | | - let left = this.int_to_int_or_float(&left, twice_wide)?; |
141 | | - let right = this.int_to_int_or_float(&right, twice_wide)?; |
142 | | - |
143 | | - // Multiply |
144 | | - let multiplied = this.wrapping_binary_op(mir::BinOp::Mul, &left, &right)?; |
145 | | - // Keep the high half |
146 | | - let high = this.wrapping_binary_op( |
147 | | - mir::BinOp::Shr, |
148 | | - &multiplied, |
149 | | - &ImmTy::from_uint(dest.layout.size.bits(), twice_wide), |
150 | | - )?; |
151 | | - |
152 | | - // Narrow back to the original type |
153 | | - let res = this.int_to_int_or_float(&high, dest.layout)?; |
154 | | - this.write_immediate(*res, &dest)?; |
155 | | - } |
156 | | - } |
157 | | - // Used to implement the _mm_mul_epu32 function. |
158 | | - // Multiplies the the low unsigned 32-bit integers from each packed |
159 | | - // 64-bit element and stores the result as 64-bit unsigned integers. |
160 | | - "pmulu.dq" => { |
161 | | - let [left, right] = |
162 | | - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
163 | | - |
164 | | - let (left, left_len) = this.operand_to_simd(left)?; |
165 | | - let (right, right_len) = this.operand_to_simd(right)?; |
166 | | - let (dest, dest_len) = this.place_to_simd(dest)?; |
167 | | - |
168 | | - // left and right are u32x4, dest is u64x2 |
169 | | - assert_eq!(left_len, 4); |
170 | | - assert_eq!(right_len, 4); |
171 | | - assert_eq!(dest_len, 2); |
172 | | - |
173 | | - for i in 0..dest_len { |
174 | | - let op_i = i.checked_mul(2).unwrap(); |
175 | | - let left = this.read_scalar(&this.project_index(&left, op_i)?)?.to_u32()?; |
176 | | - let right = this.read_scalar(&this.project_index(&right, op_i)?)?.to_u32()?; |
177 | | - let dest = this.project_index(&dest, i)?; |
178 | | - |
179 | | - // The multiplication will not overflow because stripping the |
180 | | - // operands are expanded from 32-bit to 64-bit. |
181 | | - let res = u64::from(left).checked_mul(u64::from(right)).unwrap(); |
182 | | - this.write_scalar(Scalar::from_u64(res), &dest)?; |
183 | | - } |
184 | | - } |
185 | 74 | // Used to implement the _mm_sad_epu8 function. |
186 | 75 | // Computes the absolute differences of packed unsigned 8-bit integers in `a` |
187 | 76 | // and `b`, then horizontally sum each consecutive 8 differences to produce |
@@ -370,25 +259,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: |
370 | 259 | this.write_scalar(Scalar::from_u64(res), &dest)?; |
371 | 260 | } |
372 | 261 | } |
373 | | - // Used to implement the _mm_cvtepi32_ps function. |
374 | | - // Converts packed i32 to packed f32. |
375 | | - // FIXME: Can we get rid of this intrinsic and just use simd_as? |
376 | | - "cvtdq2ps" => { |
377 | | - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
378 | | - |
379 | | - let (op, op_len) = this.operand_to_simd(op)?; |
380 | | - let (dest, dest_len) = this.place_to_simd(dest)?; |
381 | | - |
382 | | - assert_eq!(dest_len, op_len); |
383 | | - |
384 | | - for i in 0..dest_len { |
385 | | - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_i32()?; |
386 | | - let dest = this.project_index(&dest, i)?; |
387 | | - |
388 | | - let res = Scalar::from_f32(Single::from_i128(op.into()).value); |
389 | | - this.write_scalar(res, &dest)?; |
390 | | - } |
391 | | - } |
392 | 262 | // Used to implement the _mm_cvtps_epi32 and _mm_cvttps_epi32 functions. |
393 | 263 | // Converts packed f32 to packed i32. |
394 | 264 | "cvtps2dq" | "cvttps2dq" => { |
@@ -652,31 +522,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: |
652 | 522 | }; |
653 | 523 | this.write_scalar(Scalar::from_i32(i32::from(res)), dest)?; |
654 | 524 | } |
655 | | - // Used to implement the _mm_cvtpd_ps and _mm_cvtps_pd functions. |
656 | | - // Converts packed f32/f64 to packed f64/f32. |
657 | | - "cvtpd2ps" | "cvtps2pd" => { |
658 | | - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
659 | | - |
660 | | - let (op, op_len) = this.operand_to_simd(op)?; |
661 | | - let (dest, dest_len) = this.place_to_simd(dest)?; |
662 | | - |
663 | | - // For cvtpd2ps: op is f64x2, dest is f32x4 |
664 | | - // For cvtps2pd: op is f32x4, dest is f64x2 |
665 | | - // In either case, the two first values are converted |
666 | | - for i in 0..op_len.min(dest_len) { |
667 | | - let op = this.read_immediate(&this.project_index(&op, i)?)?; |
668 | | - let dest = this.project_index(&dest, i)?; |
669 | | - |
670 | | - let res = this.float_to_float_or_int(&op, dest.layout)?; |
671 | | - this.write_immediate(*res, &dest)?; |
672 | | - } |
673 | | - // For f32 -> f64, ignore the remaining |
674 | | - // For f64 -> f32, fill the remaining with zeros |
675 | | - for i in op_len..dest_len { |
676 | | - let dest = this.project_index(&dest, i)?; |
677 | | - this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?; |
678 | | - } |
679 | | - } |
680 | 525 | // Used to implement the _mm_cvtpd_epi32 and _mm_cvttpd_epi32 functions. |
681 | 526 | // Converts packed f64 to packed i32. |
682 | 527 | "cvtpd2dq" | "cvttpd2dq" => { |
@@ -772,25 +617,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: |
772 | 617 | )?; |
773 | 618 | } |
774 | 619 | } |
775 | | - // Used to implement the _mm_movemask_pd function. |
776 | | - // Returns a scalar integer where the i-th bit is the highest |
777 | | - // bit of the i-th component of `op`. |
778 | | - // https://www.felixcloutier.com/x86/movmskpd |
779 | | - "movmsk.pd" => { |
780 | | - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; |
781 | | - let (op, op_len) = this.operand_to_simd(op)?; |
782 | | - |
783 | | - let mut res = 0; |
784 | | - for i in 0..op_len { |
785 | | - let op = this.read_scalar(&this.project_index(&op, i)?)?; |
786 | | - let op = op.to_u64()?; |
787 | | - |
788 | | - // Extract the highest bit of `op` and place it in the `i`-th bit of `res` |
789 | | - res |= (op >> 63) << i; |
790 | | - } |
791 | | - |
792 | | - this.write_scalar(Scalar::from_u32(res.try_into().unwrap()), dest)?; |
793 | | - } |
794 | 620 | // Used to implement the `_mm_pause` function. |
795 | 621 | // The intrinsic is used to hint the processor that the code is in a spin-loop. |
796 | 622 | "pause" => { |
|
0 commit comments