@@ -337,36 +337,39 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
337
337
let vector = args[ 0 ] . immediate ( ) ;
338
338
let vector_type = vector. get_type ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
339
339
let elem_type = vector_type. get_element_type ( ) ;
340
- let mut shifts = vec ! [ ] ;
341
- let mut masks = vec ! [ ] ;
342
- let mut mask = 1 ;
343
- for i in 0 ..in_len {
344
- shifts. push ( bx. context . new_rvalue_from_int ( elem_type, i as i32 ) ) ;
345
- masks. push ( bx. context . new_rvalue_from_int ( elem_type, mask) ) ;
346
- mask <<= 1 ;
347
- }
348
- masks. reverse ( ) ;
349
- let shifts = bx. context . new_rvalue_from_vector ( None , vector. get_type ( ) , & shifts) ;
350
- let shifted = vector >> shifts;
351
- let masks = bx. context . new_rvalue_from_vector ( None , vector. get_type ( ) , & masks) ;
352
- let masked = shifted & masks;
353
- let reduced = bx. vector_reduce_op ( masked, BinaryOp :: BitwiseOr ) ;
354
340
355
341
let expected_int_bits = in_len. max ( 8 ) ;
356
342
let expected_bytes = expected_int_bits / 8 + ( ( expected_int_bits % 8 > 0 ) as u64 ) ;
357
343
344
+ // FIXME(antoyo): that's not going to work for masks bigger than 128 bits.
345
+ let result_type = bx. type_ix ( expected_int_bits) ;
346
+ let mut result = bx. context . new_rvalue_zero ( result_type) ;
347
+
348
+ let elem_size = elem_type. get_size ( ) * 8 ;
349
+ let sign_shift = bx. context . new_rvalue_from_int ( elem_type, elem_size as i32 ) ;
350
+ let one = bx. context . new_rvalue_one ( elem_type) ;
351
+
352
+ let mut shift = 0 ;
353
+ for i in 0 ..in_len {
354
+ let elem = bx. extract_element ( vector, bx. context . new_rvalue_from_int ( bx. int_type , i as i32 ) ) ;
355
+ let shifted = elem >> sign_shift;
356
+ let masked = shifted & one;
357
+ result = result | ( bx. context . new_cast ( None , masked, result_type) << bx. context . new_rvalue_from_int ( result_type, shift) ) ;
358
+ shift += 1 ;
359
+ }
360
+
358
361
match ret_ty. kind ( ) {
359
362
ty:: Uint ( i) if i. bit_width ( ) == Some ( expected_int_bits) => {
360
363
// Zero-extend iN to the bitmask type:
361
- return Ok ( bx . zext ( reduced , bx . type_ix ( expected_int_bits ) ) ) ;
364
+ return Ok ( result ) ;
362
365
}
363
366
ty:: Array ( elem, len)
364
367
if matches ! ( elem. kind( ) , ty:: Uint ( ty:: UintTy :: U8 ) )
365
368
&& len. try_eval_usize ( bx. tcx , ty:: ParamEnv :: reveal_all ( ) )
366
369
== Some ( expected_bytes) =>
367
370
{
368
371
// Zero-extend iN to the array length:
369
- let ze = bx. zext ( reduced , bx. type_ix ( expected_bytes * 8 ) ) ;
372
+ let ze = bx. zext ( result , bx. type_ix ( expected_bytes * 8 ) ) ;
370
373
371
374
// Convert the integer to a byte array
372
375
let ptr = bx. alloca ( bx. type_ix ( expected_bytes * 8 ) , Align :: ONE ) ;
0 commit comments