@@ -21,7 +21,7 @@ fn report_simd_type_validation_error(
2121pub ( super ) fn codegen_simd_intrinsic_call < ' tcx > (
2222 fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
2323 intrinsic : Symbol ,
24- _args : GenericArgsRef < ' tcx > ,
24+ generic_args : GenericArgsRef < ' tcx > ,
2525 args : & [ mir:: Operand < ' tcx > ] ,
2626 ret : CPlace < ' tcx > ,
2727 target : BasicBlock ,
@@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
117117 } ) ;
118118 }
119119
120+ // simd_shuffle_generic<T, U, const I: &[u32]>(x: T, y: T) -> U
121+ sym:: simd_shuffle_generic => {
122+ let [ x, y] = args else {
123+ bug ! ( "wrong number of args for intrinsic {intrinsic}" ) ;
124+ } ;
125+ let x = codegen_operand ( fx, x) ;
126+ let y = codegen_operand ( fx, y) ;
127+
128+ if !x. layout ( ) . ty . is_simd ( ) {
129+ report_simd_type_validation_error ( fx, intrinsic, span, x. layout ( ) . ty ) ;
130+ return ;
131+ }
132+
133+ let idx = generic_args[ 2 ]
134+ . expect_const ( )
135+ . eval ( fx. tcx , ty:: ParamEnv :: reveal_all ( ) , Some ( span) )
136+ . unwrap ( )
137+ . unwrap_branch ( ) ;
138+
139+ assert_eq ! ( x. layout( ) , y. layout( ) ) ;
140+ let layout = x. layout ( ) ;
141+
142+ let ( lane_count, lane_ty) = layout. ty . simd_size_and_type ( fx. tcx ) ;
143+ let ( ret_lane_count, ret_lane_ty) = ret. layout ( ) . ty . simd_size_and_type ( fx. tcx ) ;
144+
145+ assert_eq ! ( lane_ty, ret_lane_ty) ;
146+ assert_eq ! ( idx. len( ) as u64 , ret_lane_count) ;
147+
148+ let total_len = lane_count * 2 ;
149+
150+ let indexes =
151+ idx. iter ( ) . map ( |idx| idx. unwrap_leaf ( ) . try_to_u16 ( ) . unwrap ( ) ) . collect :: < Vec < u16 > > ( ) ;
152+
153+ for & idx in & indexes {
154+ assert ! ( u64 :: from( idx) < total_len, "idx {} out of range 0..{}" , idx, total_len) ;
155+ }
156+
157+ for ( out_idx, in_idx) in indexes. into_iter ( ) . enumerate ( ) {
158+ let in_lane = if u64:: from ( in_idx) < lane_count {
159+ x. value_lane ( fx, in_idx. into ( ) )
160+ } else {
161+ y. value_lane ( fx, u64:: from ( in_idx) - lane_count)
162+ } ;
163+ let out_lane = ret. place_lane ( fx, u64:: try_from ( out_idx) . unwrap ( ) ) ;
164+ out_lane. write_cvalue ( fx, in_lane) ;
165+ }
166+ }
167+
120168 // simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
121169 sym:: simd_shuffle => {
122170 let ( x, y, idx) = match args {
0 commit comments