@@ -206,6 +206,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
206206 ) ;
207207 }
208208
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+
209231 if name == sym:: simd_bswap {
210232 return Ok ( simd_bswap ( bx, args[ 0 ] . immediate ( ) ) ) ;
211233 }
@@ -1434,3 +1456,60 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
14341456
14351457 unimplemented ! ( "simd {}" , name) ;
14361458}
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+ println ! ( "Vector type: {:?}" , a_type. unqualified( ) ) ;
1470+ let vector_type = a_type. unqualified ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
1471+ let num_units = vector_type. get_num_units ( ) ;
1472+ let elem_type = vector_type. get_element_type ( ) ;
1473+
1474+ let ( new_int_type, int_shift_val, int_mask) = if elem_type. is_compatible_with ( bx. u8_type ) {
1475+ ( bx. u16_type , 8 , u8:: MAX as u64 )
1476+ } else if elem_type. is_compatible_with ( bx. u16_type ) {
1477+ ( bx. u32_type , 16 , u16:: MAX as u64 )
1478+ } else if elem_type. is_compatible_with ( bx. u32_type ) {
1479+ ( bx. u64_type , 32 , u32:: MAX as u64 )
1480+ } else if elem_type. is_compatible_with ( bx. u64_type ) {
1481+ ( bx. u128_type , 64 , u64:: MAX )
1482+ } else if elem_type. is_compatible_with ( bx. i8_type ) {
1483+ ( bx. i16_type , 8 , u8:: MAX as u64 )
1484+ } else if elem_type. is_compatible_with ( bx. i16_type ) {
1485+ ( bx. i32_type , 16 , u16:: MAX as u64 )
1486+ } else if elem_type. is_compatible_with ( bx. i32_type ) {
1487+ ( bx. i64_type , 32 , u32:: MAX as u64 )
1488+ } else if elem_type. is_compatible_with ( bx. i64_type ) {
1489+ ( bx. i128_type , 64 , u64:: MAX )
1490+ } else {
1491+ unimplemented ! ( "funnel shift on {:?}" , elem_type) ;
1492+ } ;
1493+
1494+ let int_mask = bx. context . new_rvalue_from_long ( new_int_type, int_mask as i64 ) ;
1495+ let int_shift_val = bx. context . new_rvalue_from_int ( new_int_type, int_shift_val) ;
1496+ let mut elements = vec ! [ ] ;
1497+ for i in 0 ..num_units {
1498+ let index = bx. context . new_rvalue_from_int ( bx. int_type , i as i32 ) ;
1499+ let a_val = bx. context . new_vector_access ( None , a, index) . to_rvalue ( ) ;
1500+ let a_val = bx. context . new_cast ( None , a_val, new_int_type) ;
1501+ let b_val = bx. context . new_vector_access ( None , b, index) . to_rvalue ( ) ;
1502+ let b_val = bx. context . new_cast ( None , b_val, new_int_type) ;
1503+ let shift_val = bx. context . new_vector_access ( None , shift, index) . to_rvalue ( ) ;
1504+ let shift_val = bx. context . new_cast ( None , shift_val, new_int_type) ;
1505+ let mut val = a_val << int_shift_val | b_val;
1506+ if shift_left {
1507+ val = ( val << shift_val) >> int_shift_val;
1508+ } else {
1509+ val = ( val >> shift_val) & int_mask;
1510+ }
1511+ let val = bx. context . new_cast ( None , val, elem_type) ;
1512+ elements. push ( val) ;
1513+ }
1514+ bx. context . new_rvalue_from_vector ( None , a_type, & elements)
1515+ }
0 commit comments