@@ -606,27 +606,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
606606 self . pointercast ( val, self . type_ptr ( ) )
607607 }
608608
609- sym:: sve_cast => {
610- let Some ( ( in_cnt, in_elem, in_num_vecs) ) =
611- args[ 0 ] . layout . ty . scalable_vector_parts ( self . cx . tcx )
612- else {
613- bug ! ( "input parameter to `sve_cast` was not scalable vector" ) ;
614- } ;
615- let out_layout = self . layout_of ( fn_args. type_at ( 1 ) ) ;
616- let Some ( ( out_cnt, out_elem, out_num_vecs) ) =
617- out_layout. ty . scalable_vector_parts ( self . cx . tcx )
618- else {
619- bug ! ( "output parameter to `sve_cast` was not scalable vector" ) ;
620- } ;
621- assert_eq ! ( in_cnt, out_cnt) ;
622- assert_eq ! ( in_num_vecs, out_num_vecs) ;
623- let out_llty = self . backend_type ( out_layout) ;
624- match simd_cast ( self , sym:: simd_cast, args, out_llty, in_elem, out_elem) {
625- Some ( val) => val,
626- _ => bug ! ( "could not cast scalable vectors" ) ,
627- }
628- }
629-
630609 sym:: sve_tuple_create2 => {
631610 assert_matches ! (
632611 self . layout_of( fn_args. type_at( 0 ) ) . backend_repr,
@@ -1668,6 +1647,23 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
16681647 } } ;
16691648 }
16701649
1650+ macro_rules! require_simd_or_scalable {
1651+ ( $ty: expr, $variant: ident) => { {
1652+ require!(
1653+ $ty. is_simd( ) || $ty. is_scalable_vector( ) ,
1654+ InvalidMonomorphization :: $variant { span, name, ty: $ty }
1655+ ) ;
1656+ if $ty. is_simd( ) {
1657+ let ( len, ty) = $ty. simd_size_and_type( bx. tcx( ) ) ;
1658+ ( len, ty, None )
1659+ } else {
1660+ let ( count, ty, num_vecs) =
1661+ $ty. scalable_vector_parts( bx. tcx( ) ) . expect( "`is_scalable_vector` was wrong" ) ;
1662+ ( count as u64 , ty, Some ( num_vecs) )
1663+ }
1664+ } } ;
1665+ }
1666+
16711667 /// Returns the bitwidth of the `$ty` argument if it is an `Int` or `Uint` type.
16721668 macro_rules! require_int_or_uint_ty {
16731669 ( $ty: expr, $diag: expr) => {
@@ -1787,8 +1783,19 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
17871783 return Ok ( splat) ;
17881784 }
17891785
1790- // every intrinsic below takes a SIMD vector as its first argument
1791- let ( in_len, in_elem) = require_simd ! ( args[ 0 ] . layout. ty, SimdInput ) ;
1786+ let supports_scalable = match name {
1787+ sym:: simd_cast | sym:: simd_select => true ,
1788+ _ => false ,
1789+ } ;
1790+
1791+ // Every intrinsic below takes a SIMD vector as its first argument. Some intrinsics also accept
1792+ // scalable vectors. `require_simd_or_scalable` is used regardless as it'll do the right thing
1793+ // for non-scalable vectors, and an additional check to prohibit scalable vectors for those
1794+ // intrinsics that do not support them is added.
1795+ if !supports_scalable {
1796+ let _ = require_simd ! ( args[ 0 ] . layout. ty, SimdInput ) ;
1797+ }
1798+ let ( in_len, in_elem, in_num_vecs) = require_simd_or_scalable ! ( args[ 0 ] . layout. ty, SimdInput ) ;
17921799 let in_ty = args[ 0 ] . layout . ty ;
17931800
17941801 let comparison = match name {
@@ -1977,7 +1984,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
19771984 if name == sym:: simd_select {
19781985 let m_elem_ty = in_elem;
19791986 let m_len = in_len;
1980- let ( v_len, _) = require_simd ! ( args[ 1 ] . layout. ty, SimdArgument ) ;
1987+ let ( v_len, _, _ ) = require_simd_or_scalable ! ( args[ 1 ] . layout. ty, SimdArgument ) ;
19811988 require ! (
19821989 m_len == v_len,
19831990 InvalidMonomorphization :: MismatchedLengths { span, name, m_len, v_len }
@@ -2781,7 +2788,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
27812788 }
27822789
27832790 if name == sym:: simd_cast || name == sym:: simd_as {
2784- let ( out_len, out_elem) = require_simd ! ( ret_ty, SimdReturn ) ;
2791+ let ( out_len, out_elem, out_num_vecs ) = require_simd_or_scalable ! ( ret_ty, SimdReturn ) ;
27852792 require ! (
27862793 in_len == out_len,
27872794 InvalidMonomorphization :: ReturnLengthInputType {
@@ -2793,9 +2800,99 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
27932800 out_len
27942801 }
27952802 ) ;
2796- match simd_cast ( bx, name, args, llret_ty, in_elem, out_elem) {
2797- Some ( val) => return Ok ( val) ,
2798- None => return_error ! ( InvalidMonomorphization :: UnsupportedCast {
2803+ require ! (
2804+ in_num_vecs == out_num_vecs,
2805+ InvalidMonomorphization :: ReturnNumVecsInputType {
2806+ span,
2807+ name,
2808+ in_num_vecs: in_num_vecs. unwrap_or( NumScalableVectors ( 1 ) ) ,
2809+ in_ty,
2810+ ret_ty,
2811+ out_num_vecs: out_num_vecs. unwrap_or( NumScalableVectors ( 1 ) )
2812+ }
2813+ ) ;
2814+
2815+ // Casting cares about nominal type, not just structural type
2816+ if in_elem == out_elem {
2817+ return Ok ( args[ 0 ] . immediate ( ) ) ;
2818+ }
2819+
2820+ #[ derive( Copy , Clone ) ]
2821+ enum Sign {
2822+ Unsigned ,
2823+ Signed ,
2824+ }
2825+ use Sign :: * ;
2826+
2827+ enum Style {
2828+ Float ,
2829+ Int ( Sign ) ,
2830+ Unsupported ,
2831+ }
2832+
2833+ let ( in_style, in_width) = match in_elem. kind ( ) {
2834+ // vectors of pointer-sized integers should've been
2835+ // disallowed before here, so this unwrap is safe.
2836+ ty:: Int ( i) => (
2837+ Style :: Int ( Signed ) ,
2838+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2839+ ) ,
2840+ ty:: Uint ( u) => (
2841+ Style :: Int ( Unsigned ) ,
2842+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2843+ ) ,
2844+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2845+ _ => ( Style :: Unsupported , 0 ) ,
2846+ } ;
2847+ let ( out_style, out_width) = match out_elem. kind ( ) {
2848+ ty:: Int ( i) => (
2849+ Style :: Int ( Signed ) ,
2850+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2851+ ) ,
2852+ ty:: Uint ( u) => (
2853+ Style :: Int ( Unsigned ) ,
2854+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2855+ ) ,
2856+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2857+ _ => ( Style :: Unsupported , 0 ) ,
2858+ } ;
2859+
2860+ match ( in_style, out_style) {
2861+ ( Style :: Int ( sign) , Style :: Int ( _) ) => {
2862+ return Ok ( match in_width. cmp ( & out_width) {
2863+ Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2864+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2865+ Ordering :: Less => match sign {
2866+ Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2867+ Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2868+ } ,
2869+ } ) ;
2870+ }
2871+ ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => {
2872+ return Ok ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2873+ }
2874+ ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
2875+ return Ok ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2876+ }
2877+ ( Style :: Float , Style :: Int ( sign) ) => {
2878+ return Ok ( match ( sign, name == sym:: simd_as) {
2879+ ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
2880+ ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
2881+ ( _, true ) => bx. cast_float_to_int (
2882+ matches ! ( sign, Sign :: Signed ) ,
2883+ args[ 0 ] . immediate ( ) ,
2884+ llret_ty,
2885+ ) ,
2886+ } ) ;
2887+ }
2888+ ( Style :: Float , Style :: Float ) => {
2889+ return Ok ( match in_width. cmp ( & out_width) {
2890+ Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2891+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2892+ Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2893+ } ) ;
2894+ }
2895+ _ => return_error ! ( InvalidMonomorphization :: UnsupportedCast {
27992896 span,
28002897 name,
28012898 in_ty,
@@ -2977,86 +3074,3 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
29773074
29783075 span_bug ! ( span, "unknown SIMD intrinsic" ) ;
29793076}
2980-
2981- /// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`.
2982- fn simd_cast < ' ll , ' tcx > (
2983- bx : & mut Builder < ' _ , ' ll , ' tcx > ,
2984- name : Symbol ,
2985- args : & [ OperandRef < ' tcx , & ' ll Value > ] ,
2986- llret_ty : & ' ll Type ,
2987- in_elem : Ty < ' tcx > ,
2988- out_elem : Ty < ' tcx > ,
2989- ) -> Option < & ' ll Value > {
2990- // Casting cares about nominal type, not just structural type
2991- if in_elem == out_elem {
2992- return Some ( args[ 0 ] . immediate ( ) ) ;
2993- }
2994-
2995- #[ derive( Copy , Clone ) ]
2996- enum Sign {
2997- Unsigned ,
2998- Signed ,
2999- }
3000- use Sign :: * ;
3001-
3002- enum Style {
3003- Float ,
3004- Int ( Sign ) ,
3005- Unsupported ,
3006- }
3007-
3008- let ( in_style, in_width) = match in_elem. kind ( ) {
3009- // vectors of pointer-sized integers should've been
3010- // disallowed before here, so this unwrap is safe.
3011- ty:: Int ( i) => (
3012- Style :: Int ( Signed ) ,
3013- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3014- ) ,
3015- ty:: Uint ( u) => (
3016- Style :: Int ( Unsigned ) ,
3017- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3018- ) ,
3019- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3020- _ => ( Style :: Unsupported , 0 ) ,
3021- } ;
3022- let ( out_style, out_width) = match out_elem. kind ( ) {
3023- ty:: Int ( i) => (
3024- Style :: Int ( Signed ) ,
3025- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3026- ) ,
3027- ty:: Uint ( u) => (
3028- Style :: Int ( Unsigned ) ,
3029- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3030- ) ,
3031- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3032- _ => ( Style :: Unsupported , 0 ) ,
3033- } ;
3034-
3035- match ( in_style, out_style) {
3036- ( Style :: Int ( sign) , Style :: Int ( _) ) => Some ( match in_width. cmp ( & out_width) {
3037- Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3038- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3039- Ordering :: Less => match sign {
3040- Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3041- Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3042- } ,
3043- } ) ,
3044- ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => Some ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ,
3045- ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
3046- Some ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) )
3047- }
3048- ( Style :: Float , Style :: Int ( sign) ) => Some ( match ( sign, name == sym:: simd_as) {
3049- ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
3050- ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
3051- ( _, true ) => {
3052- bx. cast_float_to_int ( matches ! ( sign, Sign :: Signed ) , args[ 0 ] . immediate ( ) , llret_ty)
3053- }
3054- } ) ,
3055- ( Style :: Float , Style :: Float ) => Some ( match in_width. cmp ( & out_width) {
3056- Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3057- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3058- Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3059- } ) ,
3060- _ => None ,
3061- }
3062- }
0 commit comments