@@ -202,14 +202,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
202202 } ;
203203 let builtin = bx. context . get_target_builtin_function ( func_name) ;
204204 let param1_type = builtin. get_param ( 0 ) . to_rvalue ( ) . get_type ( ) ;
205- let vector =
206- if vector. get_type ( ) != param1_type {
207- // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
208- bx. context . new_bitcast ( None , vector, param1_type)
209- }
210- else {
211- vector
212- } ;
205+ // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
206+ let vector = bx. cx . bitcast_if_needed ( vector, param1_type) ;
213207 let result = bx. context . new_call ( None , builtin, & [ vector, value, bx. context . new_cast ( None , index, bx. int_type ) ] ) ;
214208 // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
215209 return Ok ( bx. context . new_bitcast ( None , result, vector. get_type ( ) ) ) ;
@@ -539,18 +533,79 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
539533 let vec_ty = bx. cx . type_vector ( elem_ty, in_len as u64 ) ;
540534
541535 let func = bx. context . get_target_builtin_function ( builtin_name) ;
542- let param1_type = func. get_parameter ( 0 ) . get_type ( ) ;
543- let lhs =
544- if lhs. get_type ( ) != param1_type {
545- bx. context . new_bitcast ( None , lhs, param1_type)
546- }
547- else {
548- lhs
549- } ;
536+ let param1_type = func. get_param ( 0 ) . to_rvalue ( ) . get_type ( ) ;
537+ let param2_type = func. get_param ( 1 ) . to_rvalue ( ) . get_type ( ) ;
538+ let lhs = bx. cx . bitcast_if_needed ( lhs, param1_type) ;
539+ let rhs = bx. cx . bitcast_if_needed ( rhs, param2_type) ;
550540 let result = bx. context . new_call ( None , func, & [ lhs, rhs] ) ;
551541 // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
552542 return Ok ( bx. context . new_bitcast ( None , result, vec_ty) ) ;
553543 }
554544
545+ macro_rules! arith_red {
546+ ( $name: ident : $integer_reduce: ident, $float_reduce: ident, $ordered: expr, $op: ident,
547+ $identity: expr) => {
548+ if name == sym:: $name {
549+ require!(
550+ ret_ty == in_elem,
551+ "expected return type `{}` (element of input `{}`), found `{}`" ,
552+ in_elem,
553+ in_ty,
554+ ret_ty
555+ ) ;
556+ return match in_elem. kind( ) {
557+ ty:: Int ( _) | ty:: Uint ( _) => {
558+ let r = bx. $integer_reduce( args[ 0 ] . immediate( ) ) ;
559+ if $ordered {
560+ // if overflow occurs, the result is the
561+ // mathematical result modulo 2^n:
562+ Ok ( bx. $op( args[ 1 ] . immediate( ) , r) )
563+ } else {
564+ Ok ( bx. $integer_reduce( args[ 0 ] . immediate( ) ) )
565+ }
566+ }
567+ ty:: Float ( f) => {
568+ let acc = if $ordered {
569+ // ordered arithmetic reductions take an accumulator
570+ args[ 1 ] . immediate( )
571+ } else {
572+ // unordered arithmetic reductions use the identity accumulator
573+ match f. bit_width( ) {
574+ 32 => bx. const_real( bx. type_f32( ) , $identity) ,
575+ 64 => bx. const_real( bx. type_f64( ) , $identity) ,
576+ v => return_error!(
577+ r#"
578+ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"# ,
579+ sym:: $name,
580+ in_ty,
581+ in_elem,
582+ v,
583+ ret_ty
584+ ) ,
585+ }
586+ } ;
587+ Ok ( bx. $float_reduce( acc, args[ 0 ] . immediate( ) ) )
588+ }
589+ _ => return_error!(
590+ "unsupported {} from `{}` with element `{}` to `{}`" ,
591+ sym:: $name,
592+ in_ty,
593+ in_elem,
594+ ret_ty
595+ ) ,
596+ } ;
597+ }
598+ } ;
599+ }
600+
601+ // TODO: use a recursive algorithm a-la Hacker's Delight.
602+ arith_red ! (
603+ simd_reduce_add_unordered: vector_reduce_add,
604+ vector_reduce_fadd_fast,
605+ false ,
606+ add,
607+ 0.0
608+ ) ;
609+
555610 unimplemented ! ( "simd {}" , name) ;
556611}
0 commit comments