@@ -337,36 +337,39 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
337337 let vector = args[ 0 ] . immediate ( ) ;
338338 let vector_type = vector. get_type ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
339339 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 ) ;
354340
355341 let expected_int_bits = in_len. max ( 8 ) ;
356342 let expected_bytes = expected_int_bits / 8 + ( ( expected_int_bits % 8 > 0 ) as u64 ) ;
357343
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+
358361 match ret_ty. kind ( ) {
359362 ty:: Uint ( i) if i. bit_width ( ) == Some ( expected_int_bits) => {
360363 // Zero-extend iN to the bitmask type:
361- return Ok ( bx . zext ( reduced , bx . type_ix ( expected_int_bits ) ) ) ;
364+ return Ok ( result ) ;
362365 }
363366 ty:: Array ( elem, len)
364367 if matches ! ( elem. kind( ) , ty:: Uint ( ty:: UintTy :: U8 ) )
365368 && len. try_eval_usize ( bx. tcx , ty:: ParamEnv :: reveal_all ( ) )
366369 == Some ( expected_bytes) =>
367370 {
368371 // 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 ) ) ;
370373
371374 // Convert the integer to a byte array
372375 let ptr = bx. alloca ( bx. type_ix ( expected_bytes * 8 ) , Align :: ONE ) ;
0 commit comments