@@ -14,7 +14,6 @@ use rustc_span::{Span, Symbol, sym};
14
14
use rustc_target:: abi:: Align ;
15
15
16
16
use crate :: builder:: Builder ;
17
- use crate :: intrinsic;
18
17
19
18
pub fn generic_simd_intrinsic < ' a , ' gcc , ' tcx > ( bx : & mut Builder < ' a , ' gcc , ' tcx > , name : Symbol , callee_ty : Ty < ' tcx > , args : & [ OperandRef < ' tcx , RValue < ' gcc > > ] , ret_ty : Ty < ' tcx > , llret_ty : Type < ' gcc > , span : Span ) -> Result < RValue < ' gcc > , ( ) > {
20
19
// macros for error handling:
@@ -415,8 +414,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
415
414
if let ty:: Float ( f) = in_elem. kind ( ) {
416
415
let elem_ty = bx. cx . type_float_from_ty ( * f) ;
417
416
match f. bit_width ( ) {
418
- 32 => ( "f32 " , elem_ty) ,
419
- 64 => ( "f64 " , elem_ty) ,
417
+ 32 => ( "f " , elem_ty) ,
418
+ 64 => ( "" , elem_ty) ,
420
419
_ => {
421
420
return_error ! (
422
421
"unsupported element type `{}` of floating-point vector `{}`" ,
@@ -432,30 +431,49 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
432
431
433
432
let vec_ty = bx. cx . type_vector ( elem_ty, in_len) ;
434
433
435
- let ( intr_name, fn_ty ) =
434
+ let intr_name =
436
435
match name {
437
- sym:: simd_ceil => ( "ceil" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
438
- sym:: simd_fabs => ( "fabs" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) , // TODO(antoyo): pand with 170141183420855150465331762880109871103
439
- sym:: simd_fcos => ( "cos" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
440
- sym:: simd_fexp2 => ( "exp2" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
441
- sym:: simd_fexp => ( "exp" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
442
- sym:: simd_flog10 => ( "log10" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
443
- sym:: simd_flog2 => ( "log2" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
444
- sym:: simd_flog => ( "log" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
445
- sym:: simd_floor => ( "floor" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
446
- sym:: simd_fma => ( "fma" , bx . type_func ( & [ vec_ty , vec_ty , vec_ty ] , vec_ty ) ) ,
447
- sym:: simd_fpowi => ( "powi" , bx . type_func ( & [ vec_ty , bx . type_i32 ( ) ] , vec_ty ) ) ,
448
- sym:: simd_fpow => ( "pow" , bx . type_func ( & [ vec_ty , vec_ty ] , vec_ty ) ) ,
449
- sym:: simd_fsin => ( "sin" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
450
- sym:: simd_fsqrt => ( "sqrt" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
451
- sym:: simd_round => ( "round" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
452
- sym:: simd_trunc => ( "trunc" , bx . type_func ( & [ vec_ty ] , vec_ty ) ) ,
436
+ sym:: simd_ceil => "ceil" ,
437
+ sym:: simd_fabs => "fabs" , // TODO(antoyo): pand with 170141183420855150465331762880109871103
438
+ sym:: simd_fcos => "cos" ,
439
+ sym:: simd_fexp2 => "exp2" ,
440
+ sym:: simd_fexp => "exp" ,
441
+ sym:: simd_flog10 => "log10" ,
442
+ sym:: simd_flog2 => "log2" ,
443
+ sym:: simd_flog => "log" ,
444
+ sym:: simd_floor => "floor" ,
445
+ sym:: simd_fma => "fma" ,
446
+ sym:: simd_fpowi => "__builtin_powi" ,
447
+ sym:: simd_fpow => "pow" ,
448
+ sym:: simd_fsin => "sin" ,
449
+ sym:: simd_fsqrt => "sqrt" ,
450
+ sym:: simd_round => "round" ,
451
+ sym:: simd_trunc => "trunc" ,
453
452
_ => return_error ! ( "unrecognized intrinsic `{}`" , name) ,
454
453
} ;
455
- let llvm_name = & format ! ( "llvm.{0}.v{1}{2}" , intr_name, in_len, elem_ty_str) ;
456
- let function = intrinsic:: llvm:: intrinsic ( llvm_name, & bx. cx ) ;
457
- let function: RValue < ' gcc > = unsafe { std:: mem:: transmute ( function) } ;
458
- let c = bx. call ( fn_ty, function, & args. iter ( ) . map ( |arg| arg. immediate ( ) ) . collect :: < Vec < _ > > ( ) , None ) ;
454
+ let builtin_name = format ! ( "{}{}" , intr_name, elem_ty_str) ;
455
+ let funcs = bx. cx . functions . borrow ( ) ;
456
+ let function = funcs. get ( & builtin_name) . unwrap_or_else ( || panic ! ( "unable to find builtin function {}" , builtin_name) ) ;
457
+
458
+ // TODO(antoyo): add platform-specific behavior here for architectures that have these
459
+ // intrinsics as instructions (for instance, gpus)
460
+ let mut vector_elements = vec ! [ ] ;
461
+ for i in 0 ..in_len {
462
+ let index = bx. context . new_rvalue_from_long ( bx. ulong_type , i as i64 ) ;
463
+ // we have to treat fpowi specially, since fpowi's second argument is always an i32
464
+ let arguments = if name == sym:: simd_fpowi {
465
+ vec ! [
466
+ bx. extract_element( args[ 0 ] . immediate( ) , index) . to_rvalue( ) ,
467
+ args[ 1 ] . immediate( ) ,
468
+ ]
469
+ } else {
470
+ args. iter ( )
471
+ . map ( |arg| bx. extract_element ( arg. immediate ( ) , index) . to_rvalue ( ) )
472
+ . collect ( )
473
+ } ;
474
+ vector_elements. push ( bx. context . new_call ( None , * function, & arguments) ) ;
475
+ }
476
+ let c = bx. context . new_rvalue_from_vector ( None , vec_ty, & vector_elements) ;
459
477
Ok ( c)
460
478
}
461
479
0 commit comments