@@ -582,6 +582,27 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
582582 self . pointercast ( val, self . type_ptr ( ) )
583583 }
584584
585+ sym:: sve_cast => {
586+ let Some ( ( in_cnt, in_elem, in_num_vecs) ) =
587+ args[ 0 ] . layout . ty . scalable_vector_parts ( self . cx . tcx )
588+ else {
589+ bug ! ( "input parameter to `sve_cast` was not scalable vector" ) ;
590+ } ;
591+ let out_layout = self . layout_of ( fn_args. type_at ( 1 ) ) ;
592+ let Some ( ( out_cnt, out_elem, out_num_vecs) ) =
593+ out_layout. ty . scalable_vector_parts ( self . cx . tcx )
594+ else {
595+ bug ! ( "output parameter to `sve_cast` was not scalable vector" ) ;
596+ } ;
597+ assert_eq ! ( in_cnt, out_cnt) ;
598+ assert_eq ! ( in_num_vecs, out_num_vecs) ;
599+ let out_llty = self . backend_type ( out_layout) ;
600+ match simd_cast ( self , sym:: simd_cast, args, out_llty, in_elem, out_elem) {
601+ Some ( val) => val,
602+ _ => bug ! ( "could not cast scalable vectors" ) ,
603+ }
604+ }
605+
585606 sym:: sve_tuple_create2 => {
586607 assert_matches ! (
587608 self . layout_of( fn_args. type_at( 0 ) ) . backend_repr,
@@ -2769,96 +2790,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
27692790 out_len
27702791 }
27712792 ) ;
2772- // casting cares about nominal type, not just structural type
2773- if in_elem == out_elem {
2774- return Ok ( args[ 0 ] . immediate ( ) ) ;
2775- }
2776-
2777- #[ derive( Copy , Clone ) ]
2778- enum Sign {
2779- Unsigned ,
2780- Signed ,
2781- }
2782- use Sign :: * ;
2783-
2784- enum Style {
2785- Float ,
2786- Int ( Sign ) ,
2787- Unsupported ,
2788- }
2789-
2790- let ( in_style, in_width) = match in_elem. kind ( ) {
2791- // vectors of pointer-sized integers should've been
2792- // disallowed before here, so this unwrap is safe.
2793- ty:: Int ( i) => (
2794- Style :: Int ( Signed ) ,
2795- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2796- ) ,
2797- ty:: Uint ( u) => (
2798- Style :: Int ( Unsigned ) ,
2799- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2800- ) ,
2801- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2802- _ => ( Style :: Unsupported , 0 ) ,
2803- } ;
2804- let ( out_style, out_width) = match out_elem. kind ( ) {
2805- ty:: Int ( i) => (
2806- Style :: Int ( Signed ) ,
2807- i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2808- ) ,
2809- ty:: Uint ( u) => (
2810- Style :: Int ( Unsigned ) ,
2811- u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
2812- ) ,
2813- ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
2814- _ => ( Style :: Unsupported , 0 ) ,
2815- } ;
2816-
2817- match ( in_style, out_style) {
2818- ( Style :: Int ( sign) , Style :: Int ( _) ) => {
2819- return Ok ( match in_width. cmp ( & out_width) {
2820- Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2821- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2822- Ordering :: Less => match sign {
2823- Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2824- Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2825- } ,
2826- } ) ;
2827- }
2828- ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => {
2829- return Ok ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2830- }
2831- ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
2832- return Ok ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ;
2833- }
2834- ( Style :: Float , Style :: Int ( sign) ) => {
2835- return Ok ( match ( sign, name == sym:: simd_as) {
2836- ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
2837- ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
2838- ( _, true ) => bx. cast_float_to_int (
2839- matches ! ( sign, Sign :: Signed ) ,
2840- args[ 0 ] . immediate ( ) ,
2841- llret_ty,
2842- ) ,
2843- } ) ;
2844- }
2845- ( Style :: Float , Style :: Float ) => {
2846- return Ok ( match in_width. cmp ( & out_width) {
2847- Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
2848- Ordering :: Equal => args[ 0 ] . immediate ( ) ,
2849- Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
2850- } ) ;
2851- }
2852- _ => { /* Unsupported. Fallthrough. */ }
2793+ match simd_cast ( bx, name, args, llret_ty, in_elem, out_elem) {
2794+ Some ( val) => return Ok ( val) ,
2795+ None => return_error ! ( InvalidMonomorphization :: UnsupportedCast {
2796+ span,
2797+ name,
2798+ in_ty,
2799+ in_elem,
2800+ ret_ty,
2801+ out_elem
2802+ } ) ,
28532803 }
2854- return_error ! ( InvalidMonomorphization :: UnsupportedCast {
2855- span,
2856- name,
2857- in_ty,
2858- in_elem,
2859- ret_ty,
2860- out_elem
2861- } ) ;
28622804 }
28632805 macro_rules! arith_binary {
28642806 ( $( $name: ident: $( $( $p: ident) ,* => $call: ident) ,* ; ) * ) => {
@@ -3032,3 +2974,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
30322974
30332975 span_bug ! ( span, "unknown SIMD intrinsic" ) ;
30342976}
2977+
2978+ /// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`.
2979+ fn simd_cast < ' ll , ' tcx > (
2980+ bx : & mut Builder < ' _ , ' ll , ' tcx > ,
2981+ name : Symbol ,
2982+ args : & [ OperandRef < ' tcx , & ' ll Value > ] ,
2983+ llret_ty : & ' ll Type ,
2984+ in_elem : Ty < ' tcx > ,
2985+ out_elem : Ty < ' tcx > ,
2986+ ) -> Option < & ' ll Value > {
2987+ // Casting cares about nominal type, not just structural type
2988+ if in_elem == out_elem {
2989+ return Some ( args[ 0 ] . immediate ( ) ) ;
2990+ }
2991+
2992+ #[ derive( Copy , Clone ) ]
2993+ enum Sign {
2994+ Unsigned ,
2995+ Signed ,
2996+ }
2997+ use Sign :: * ;
2998+
2999+ enum Style {
3000+ Float ,
3001+ Int ( Sign ) ,
3002+ Unsupported ,
3003+ }
3004+
3005+ let ( in_style, in_width) = match in_elem. kind ( ) {
3006+ // vectors of pointer-sized integers should've been
3007+ // disallowed before here, so this unwrap is safe.
3008+ ty:: Int ( i) => (
3009+ Style :: Int ( Signed ) ,
3010+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3011+ ) ,
3012+ ty:: Uint ( u) => (
3013+ Style :: Int ( Unsigned ) ,
3014+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3015+ ) ,
3016+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3017+ _ => ( Style :: Unsupported , 0 ) ,
3018+ } ;
3019+ let ( out_style, out_width) = match out_elem. kind ( ) {
3020+ ty:: Int ( i) => (
3021+ Style :: Int ( Signed ) ,
3022+ i. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3023+ ) ,
3024+ ty:: Uint ( u) => (
3025+ Style :: Int ( Unsigned ) ,
3026+ u. normalize ( bx. tcx ( ) . sess . target . pointer_width ) . bit_width ( ) . unwrap ( ) ,
3027+ ) ,
3028+ ty:: Float ( f) => ( Style :: Float , f. bit_width ( ) ) ,
3029+ _ => ( Style :: Unsupported , 0 ) ,
3030+ } ;
3031+
3032+ match ( in_style, out_style) {
3033+ ( Style :: Int ( sign) , Style :: Int ( _) ) => Some ( match in_width. cmp ( & out_width) {
3034+ Ordering :: Greater => bx. trunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3035+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3036+ Ordering :: Less => match sign {
3037+ Sign :: Signed => bx. sext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3038+ Sign :: Unsigned => bx. zext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3039+ } ,
3040+ } ) ,
3041+ ( Style :: Int ( Sign :: Signed ) , Style :: Float ) => Some ( bx. sitofp ( args[ 0 ] . immediate ( ) , llret_ty) ) ,
3042+ ( Style :: Int ( Sign :: Unsigned ) , Style :: Float ) => {
3043+ Some ( bx. uitofp ( args[ 0 ] . immediate ( ) , llret_ty) )
3044+ }
3045+ ( Style :: Float , Style :: Int ( sign) ) => Some ( match ( sign, name == sym:: simd_as) {
3046+ ( Sign :: Unsigned , false ) => bx. fptoui ( args[ 0 ] . immediate ( ) , llret_ty) ,
3047+ ( Sign :: Signed , false ) => bx. fptosi ( args[ 0 ] . immediate ( ) , llret_ty) ,
3048+ ( _, true ) => {
3049+ bx. cast_float_to_int ( matches ! ( sign, Sign :: Signed ) , args[ 0 ] . immediate ( ) , llret_ty)
3050+ }
3051+ } ) ,
3052+ ( Style :: Float , Style :: Float ) => Some ( match in_width. cmp ( & out_width) {
3053+ Ordering :: Greater => bx. fptrunc ( args[ 0 ] . immediate ( ) , llret_ty) ,
3054+ Ordering :: Equal => args[ 0 ] . immediate ( ) ,
3055+ Ordering :: Less => bx. fpext ( args[ 0 ] . immediate ( ) , llret_ty) ,
3056+ } ) ,
3057+ _ => None ,
3058+ }
3059+ }
0 commit comments