@@ -144,6 +144,34 @@ pub fn lane_type_and_count<'tcx>(
144
144
}
145
145
146
146
fn simd_for_each_lane<' tcx, B : Backend >(
147
+ fx: & mut FunctionCx <' _, ' tcx, B >,
148
+ intrinsic: & str,
149
+ val: CValue <' tcx>,
150
+ ret: CPlace <' tcx>,
151
+ f: impl Fn (
152
+ & mut FunctionCx <' _, ' tcx, B >,
153
+ TyLayout <' tcx>,
154
+ TyLayout <' tcx>,
155
+ Value ,
156
+ ) -> CValue <' tcx>,
157
+ ) {
158
+ let layout = val. layout ( ) ;
159
+
160
+ let ( lane_layout, lane_count) = lane_type_and_count ( fx. tcx , layout) ;
161
+ let ( ret_lane_layout, ret_lane_count) = lane_type_and_count ( fx. tcx , ret. layout ( ) ) ;
162
+ assert_eq ! ( lane_count, ret_lane_count) ;
163
+
164
+ for lane_idx in 0 ..lane_count {
165
+ let lane_idx = mir:: Field :: new ( lane_idx. try_into ( ) . unwrap ( ) ) ;
166
+ let lane = val. value_field ( fx, lane_idx) . load_scalar ( fx) ;
167
+
168
+ let res_lane = f ( fx, lane_layout, ret_lane_layout, lane) ;
169
+
170
+ ret. place_field ( fx, lane_idx) . write_cvalue ( fx, res_lane) ;
171
+ }
172
+ }
173
+
174
+ fn simd_pair_for_each_lane<' tcx, B : Backend >(
147
175
fx: & mut FunctionCx <' _, ' tcx, B >,
148
176
intrinsic: & str,
149
177
x: CValue <' tcx>,
@@ -204,7 +232,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
204
232
205
233
macro simd_cmp {
206
234
( $fx: expr, $intrinsic: expr, $cc: ident( $x: ident, $y: ident) -> $ret: ident) => {
207
- simd_for_each_lane (
235
+ simd_pair_for_each_lane (
208
236
$fx,
209
237
$intrinsic,
210
238
$x,
@@ -220,7 +248,7 @@ macro simd_cmp {
220
248
) ;
221
249
} ,
222
250
( $fx: expr, $intrinsic: expr, $cc_u: ident|$cc_s: ident( $x: ident, $y: ident) -> $ret: ident) => {
223
- simd_for_each_lane (
251
+ simd_pair_for_each_lane (
224
252
$fx,
225
253
$intrinsic,
226
254
$x,
@@ -239,94 +267,52 @@ macro simd_cmp {
239
267
}
240
268
241
269
macro simd_int_binop {
242
- ( $fx: expr, $intrinsic: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) => {
243
- simd_for_each_lane (
244
- $fx,
245
- $intrinsic,
246
- $x,
247
- $y,
248
- $ret,
249
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
250
- let res_lane = match lane_layout. ty . kind {
251
- ty:: Uint ( _) | ty:: Int ( _) => fx. bcx . ins ( ) . $op( x_lane, y_lane) ,
252
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
253
- } ;
254
- CValue :: by_val ( res_lane, ret_lane_layout)
255
- } ,
256
- ) ;
270
+ ( $fx: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) => {
271
+ simd_int_binop ! ( $fx, $op|$op( $x, $y) -> $ret) ;
257
272
} ,
258
- ( $fx: expr, $intrinsic: expr, $op_u: ident|$op_s: ident( $x: ident, $y: ident) -> $ret: ident) => {
259
- simd_for_each_lane (
260
- $fx,
261
- $intrinsic,
262
- $x,
263
- $y,
264
- $ret,
265
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
266
- let res_lane = match lane_layout. ty . kind {
267
- ty:: Uint ( _) => fx. bcx . ins ( ) . $op_u( x_lane, y_lane) ,
268
- ty:: Int ( _) => fx. bcx . ins ( ) . $op_s( x_lane, y_lane) ,
269
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
270
- } ;
271
- CValue :: by_val ( res_lane, ret_lane_layout)
272
- } ,
273
- ) ;
273
+ ( $fx: expr, $op_u: ident|$op_s: ident( $x: ident, $y: ident) -> $ret: ident) => {
274
+ let ( lane_layout, lane_count) = lane_type_and_count ( $fx. tcx , $x. layout ( ) ) ;
275
+ let x_val = $x. load_scalar ( $fx) ;
276
+ let y_val = $y. load_scalar ( $fx) ;
277
+
278
+ let res = match lane_layout. ty . kind {
279
+ ty:: Uint ( _) => $fx. bcx . ins ( ) . $op_u( x_val, y_val) ,
280
+ ty:: Int ( _) => $fx. bcx . ins ( ) . $op_s( x_val, y_val) ,
281
+ _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
282
+ } ;
283
+ $ret. write_cvalue ( $fx, CValue :: by_val ( res, $ret. layout ( ) ) ) ;
274
284
} ,
275
285
}
276
286
277
287
macro simd_int_flt_binop {
278
- ( $fx: expr, $intrinsic: expr, $op: ident|$op_f: ident ( $x: ident , $y: ident ) -> $ret: ident) => {
279
- simd_for_each_lane(
280
- $fx,
281
- $intrinsic,
282
- $x,
283
- $y,
284
- $ret,
285
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
286
- let res_lane = match lane_layout. ty. kind {
287
- ty: : Uint ( _) | ty:: Int ( _) => fx. bcx. ins( ) . $op( x_lane, y_lane) ,
288
- ty:: Float ( _) => fx. bcx. ins( ) . $op_f( x_lane, y_lane) ,
289
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
290
- } ;
291
- CValue :: by_val( res_lane, ret_lane_layout)
292
- } ,
293
- ) ;
288
+ ( $fx: expr, $op: ident|$op_f: ident ( $x: ident , $y: ident ) -> $ret: ident) => {
289
+ simd_int_flt_binop ! ( $fx, $op|$op|$op_f( $x, $y) -> $ret) ;
294
290
} ,
295
- ( $fx: expr, $intrinsic: expr, $op_u: ident|$op_s: ident |$op_f: ident( $x: ident, $y: ident) -> $ret: ident) => {
296
- simd_for_each_lane(
297
- $fx,
298
- $intrinsic,
299
- $x,
300
- $y,
301
- $ret,
302
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
303
- let res_lane = match lane_layout. ty. kind {
304
- ty: : Uint ( _) => fx. bcx. ins( ) . $op_u( x_lane, y_lane) ,
305
- ty:: Int ( _) => fx. bcx. ins( ) . $op_s( x_lane, y_lane) ,
306
- ty:: Float ( _) => fx. bcx. ins( ) . $op_f( x_lane, y_lane) ,
307
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
308
- } ;
309
- CValue :: by_val( res_lane, ret_lane_layout)
310
- } ,
311
- ) ;
291
+ ( $fx: expr, $op_u: ident|$op_s: ident |$op_f: ident( $x: ident, $y: ident) -> $ret: ident) => {
292
+ let ( lane_layout, lane_count) = lane_type_and_count ( $fx. tcx , $x. layout ( ) ) ;
293
+ let x_val = $x. load_scalar ( $fx) ;
294
+ let y_val = $y. load_scalar ( $fx) ;
295
+
296
+ let res = match lane_layout. ty . kind {
297
+ ty:: Uint ( _) => $fx. bcx . ins ( ) . $op_u( x_val, y_val) ,
298
+ ty:: Int ( _) => $fx. bcx . ins ( ) . $op_s( x_val, y_val) ,
299
+ ty:: Float ( _) => $fx. bcx . ins ( ) . $op_f( x_val, y_val) ,
300
+ _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
301
+ } ;
302
+ $ret. write_cvalue ( $fx, CValue :: by_val ( res, $ret. layout ( ) ) ) ;
312
303
} ,
313
304
}
314
305
315
- macro simd_flt_binop( $fx: expr, $intrinsic: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) {
316
- simd_for_each_lane(
317
- $fx,
318
- $intrinsic,
319
- $x,
320
- $y,
321
- $ret,
322
- |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
323
- let res_lane = match lane_layout. ty. kind {
324
- ty : : Float ( _) => fx. bcx. ins( ) . $op( x_lane, y_lane) ,
325
- _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
326
- } ;
327
- CValue :: by_val( res_lane, ret_lane_layout)
328
- } ,
329
- ) ;
306
+ macro simd_flt_binop ( $fx: expr, $op: ident( $x: ident, $y: ident) -> $ret: ident) {
307
+ let ( lane_layout, lane_count) = lane_type_and_count ( $fx. tcx , $x. layout ( ) ) ;
308
+ let x_val = $x. load_scalar ( $fx) ;
309
+ let y_val = $y. load_scalar ( $fx) ;
310
+
311
+ let res = match lane_layout. ty . kind {
312
+ ty:: Float ( _) => $fx. bcx . ins ( ) . $op( x_val, y_val) ,
313
+ _ => unreachable ! ( "{:?}" , lane_layout. ty) ,
314
+ } ;
315
+ $ret. write_cvalue ( $fx, CValue :: by_val ( res, $ret. layout ( ) ) ) ;
330
316
}
331
317
332
318
pub fn codegen_intrinsic_call < ' tcx > (
0 commit comments