@@ -202,14 +202,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
202
202
} ;
203
203
let builtin = bx. context . get_target_builtin_function ( func_name) ;
204
204
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) ;
213
207
let result = bx. context . new_call ( None , builtin, & [ vector, value, bx. context . new_cast ( None , index, bx. int_type ) ] ) ;
214
208
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
215
209
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>,
539
533
let vec_ty = bx. cx . type_vector ( elem_ty, in_len as u64 ) ;
540
534
541
535
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) ;
550
540
let result = bx. context . new_call ( None , func, & [ lhs, rhs] ) ;
551
541
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
552
542
return Ok ( bx. context . new_bitcast ( None , result, vec_ty) ) ;
553
543
}
554
544
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
+
555
610
unimplemented ! ( "simd {}" , name) ;
556
611
}
0 commit comments