@@ -206,6 +206,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
206
206
) ;
207
207
}
208
208
209
+ #[ cfg( feature = "master" ) ]
210
+ if name == sym:: simd_funnel_shl {
211
+ return Ok ( simd_funnel_shift (
212
+ bx,
213
+ args[ 0 ] . immediate ( ) ,
214
+ args[ 1 ] . immediate ( ) ,
215
+ args[ 2 ] . immediate ( ) ,
216
+ true ,
217
+ ) ) ;
218
+ }
219
+
220
+ #[ cfg( feature = "master" ) ]
221
+ if name == sym:: simd_funnel_shr {
222
+ return Ok ( simd_funnel_shift (
223
+ bx,
224
+ args[ 0 ] . immediate ( ) ,
225
+ args[ 1 ] . immediate ( ) ,
226
+ args[ 2 ] . immediate ( ) ,
227
+ false ,
228
+ ) ) ;
229
+ }
230
+
209
231
if name == sym:: simd_bswap {
210
232
return Ok ( simd_bswap ( bx, args[ 0 ] . immediate ( ) ) ) ;
211
233
}
@@ -1434,3 +1456,59 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
1434
1456
1435
1457
unimplemented ! ( "simd {}" , name) ;
1436
1458
}
1459
+
1460
+ #[ cfg( feature = "master" ) ]
1461
+ fn simd_funnel_shift < ' a , ' gcc , ' tcx > (
1462
+ bx : & mut Builder < ' a , ' gcc , ' tcx > ,
1463
+ a : RValue < ' gcc > ,
1464
+ b : RValue < ' gcc > ,
1465
+ shift : RValue < ' gcc > ,
1466
+ shift_left : bool ,
1467
+ ) -> RValue < ' gcc > {
1468
+ let a_type = a. get_type ( ) ;
1469
+ let vector_type = a_type. unqualified ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
1470
+ let num_units = vector_type. get_num_units ( ) ;
1471
+ let elem_type = vector_type. get_element_type ( ) ;
1472
+
1473
+ let ( new_int_type, int_shift_val, int_mask) = if elem_type. is_compatible_with ( bx. u8_type ) {
1474
+ ( bx. u16_type , 8 , u8:: MAX as u64 )
1475
+ } else if elem_type. is_compatible_with ( bx. u16_type ) {
1476
+ ( bx. u32_type , 16 , u16:: MAX as u64 )
1477
+ } else if elem_type. is_compatible_with ( bx. u32_type ) {
1478
+ ( bx. u64_type , 32 , u32:: MAX as u64 )
1479
+ } else if elem_type. is_compatible_with ( bx. u64_type ) {
1480
+ ( bx. u128_type , 64 , u64:: MAX )
1481
+ } else if elem_type. is_compatible_with ( bx. i8_type ) {
1482
+ ( bx. i16_type , 8 , u8:: MAX as u64 )
1483
+ } else if elem_type. is_compatible_with ( bx. i16_type ) {
1484
+ ( bx. i32_type , 16 , u16:: MAX as u64 )
1485
+ } else if elem_type. is_compatible_with ( bx. i32_type ) {
1486
+ ( bx. i64_type , 32 , u32:: MAX as u64 )
1487
+ } else if elem_type. is_compatible_with ( bx. i64_type ) {
1488
+ ( bx. i128_type , 64 , u64:: MAX )
1489
+ } else {
1490
+ unimplemented ! ( "funnel shift on {:?}" , elem_type) ;
1491
+ } ;
1492
+
1493
+ let int_mask = bx. context . new_rvalue_from_long ( new_int_type, int_mask as i64 ) ;
1494
+ let int_shift_val = bx. context . new_rvalue_from_int ( new_int_type, int_shift_val) ;
1495
+ let mut elements = vec ! [ ] ;
1496
+ for i in 0 ..num_units {
1497
+ let index = bx. context . new_rvalue_from_int ( bx. int_type , i as i32 ) ;
1498
+ let a_val = bx. context . new_vector_access ( None , a, index) . to_rvalue ( ) ;
1499
+ let a_val = bx. context . new_cast ( None , a_val, new_int_type) ;
1500
+ let b_val = bx. context . new_vector_access ( None , b, index) . to_rvalue ( ) ;
1501
+ let b_val = bx. context . new_cast ( None , b_val, new_int_type) ;
1502
+ let shift_val = bx. context . new_vector_access ( None , shift, index) . to_rvalue ( ) ;
1503
+ let shift_val = bx. context . new_cast ( None , shift_val, new_int_type) ;
1504
+ let mut val = a_val << int_shift_val | b_val;
1505
+ if shift_left {
1506
+ val = ( val << shift_val) >> int_shift_val;
1507
+ } else {
1508
+ val = ( val >> shift_val) & int_mask;
1509
+ }
1510
+ let val = bx. context . new_cast ( None , val, elem_type) ;
1511
+ elements. push ( val) ;
1512
+ }
1513
+ bx. context . new_rvalue_from_vector ( None , a_type, & elements)
1514
+ }
0 commit comments