@@ -21,7 +21,7 @@ fn report_simd_type_validation_error(
21
21
pub ( super ) fn codegen_simd_intrinsic_call < ' tcx > (
22
22
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
23
23
intrinsic : Symbol ,
24
- _args : GenericArgsRef < ' tcx > ,
24
+ generic_args : GenericArgsRef < ' tcx > ,
25
25
args : & [ mir:: Operand < ' tcx > ] ,
26
26
ret : CPlace < ' tcx > ,
27
27
target : BasicBlock ,
@@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
117
117
} ) ;
118
118
}
119
119
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
+
120
168
// simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
121
169
sym:: simd_shuffle => {
122
170
let ( x, y, idx) = match args {
0 commit comments