@@ -14,7 +14,6 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1414use rustc_codegen_ssa:: traits:: * ;
1515use rustc_data_structures:: small_c_str:: SmallCStr ;
1616use rustc_hir:: def_id:: DefId ;
17- use rustc_middle:: bug;
1817use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
1918use rustc_middle:: ty:: layout:: {
2019 FnAbiError , FnAbiOfHelpers , FnAbiRequest , HasTypingEnv , LayoutError , LayoutOfHelpers ,
@@ -484,73 +483,31 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
484483 fn checked_binop (
485484 & mut self ,
486485 oop : OverflowOp ,
487- ty : Ty < ' _ > ,
486+ ty : Ty < ' tcx > ,
488487 lhs : Self :: Value ,
489488 rhs : Self :: Value ,
490489 ) -> ( Self :: Value , Self :: Value ) {
491- use rustc_middle:: ty:: IntTy :: * ;
492- use rustc_middle:: ty:: UintTy :: * ;
493- use rustc_middle:: ty:: { Int , Uint } ;
494-
495- let new_kind = match ty. kind ( ) {
496- Int ( t @ Isize ) => Int ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
497- Uint ( t @ Usize ) => Uint ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
498- t @ ( Uint ( _) | Int ( _) ) => * t,
499- _ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
490+ let ( size, signed) = ty. int_size_and_signed ( self . tcx ) ;
491+ let width = size. bits ( ) ;
492+
493+ if oop == OverflowOp :: Sub && !signed {
494+ // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
495+ // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
496+ // in the backend if profitable.
497+ let sub = self . sub ( lhs, rhs) ;
498+ let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
499+ return ( sub, cmp) ;
500+ }
501+
502+ let oop_str = match oop {
503+ OverflowOp :: Add => "add" ,
504+ OverflowOp :: Sub => "sub" ,
505+ OverflowOp :: Mul => "mul" ,
500506 } ;
501507
502- let name = match oop {
503- OverflowOp :: Add => match new_kind {
504- Int ( I8 ) => "llvm.sadd.with.overflow.i8" ,
505- Int ( I16 ) => "llvm.sadd.with.overflow.i16" ,
506- Int ( I32 ) => "llvm.sadd.with.overflow.i32" ,
507- Int ( I64 ) => "llvm.sadd.with.overflow.i64" ,
508- Int ( I128 ) => "llvm.sadd.with.overflow.i128" ,
509-
510- Uint ( U8 ) => "llvm.uadd.with.overflow.i8" ,
511- Uint ( U16 ) => "llvm.uadd.with.overflow.i16" ,
512- Uint ( U32 ) => "llvm.uadd.with.overflow.i32" ,
513- Uint ( U64 ) => "llvm.uadd.with.overflow.i64" ,
514- Uint ( U128 ) => "llvm.uadd.with.overflow.i128" ,
515-
516- _ => unreachable ! ( ) ,
517- } ,
518- OverflowOp :: Sub => match new_kind {
519- Int ( I8 ) => "llvm.ssub.with.overflow.i8" ,
520- Int ( I16 ) => "llvm.ssub.with.overflow.i16" ,
521- Int ( I32 ) => "llvm.ssub.with.overflow.i32" ,
522- Int ( I64 ) => "llvm.ssub.with.overflow.i64" ,
523- Int ( I128 ) => "llvm.ssub.with.overflow.i128" ,
524-
525- Uint ( _) => {
526- // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
527- // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
528- // in the backend if profitable.
529- let sub = self . sub ( lhs, rhs) ;
530- let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
531- return ( sub, cmp) ;
532- }
533-
534- _ => unreachable ! ( ) ,
535- } ,
536- OverflowOp :: Mul => match new_kind {
537- Int ( I8 ) => "llvm.smul.with.overflow.i8" ,
538- Int ( I16 ) => "llvm.smul.with.overflow.i16" ,
539- Int ( I32 ) => "llvm.smul.with.overflow.i32" ,
540- Int ( I64 ) => "llvm.smul.with.overflow.i64" ,
541- Int ( I128 ) => "llvm.smul.with.overflow.i128" ,
542-
543- Uint ( U8 ) => "llvm.umul.with.overflow.i8" ,
544- Uint ( U16 ) => "llvm.umul.with.overflow.i16" ,
545- Uint ( U32 ) => "llvm.umul.with.overflow.i32" ,
546- Uint ( U64 ) => "llvm.umul.with.overflow.i64" ,
547- Uint ( U128 ) => "llvm.umul.with.overflow.i128" ,
548-
549- _ => unreachable ! ( ) ,
550- } ,
551- } ;
508+ let name = format ! ( "llvm.{}{oop_str}.with.overflow" , if signed { 's' } else { 'u' } ) ;
552509
553- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
510+ let res = self . call_intrinsic ( & name, & [ self . type_ix ( width ) ] , & [ lhs, rhs] ) ;
554511 ( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
555512 }
556513
@@ -954,11 +911,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
954911 }
955912
956913 fn fptoui_sat ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
957- self . fptoint_sat ( false , val, dest_ty )
914+ self . call_intrinsic ( "llvm.fptoui.sat" , & [ dest_ty , self . val_ty ( val) ] , & [ val ] )
958915 }
959916
960917 fn fptosi_sat ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
961- self . fptoint_sat ( true , val, dest_ty )
918+ self . call_intrinsic ( "llvm.fptosi.sat" , & [ dest_ty , self . val_ty ( val) ] , & [ val ] )
962919 }
963920
964921 fn fptoui ( & mut self , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
@@ -981,15 +938,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
981938 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
982939 let float_width = self . cx . float_width ( src_ty) ;
983940 let int_width = self . cx . int_width ( dest_ty) ;
984- let name = match ( int_width, float_width) {
985- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f32" ) ,
986- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f64" ) ,
987- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f32" ) ,
988- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f64" ) ,
989- _ => None ,
990- } ;
991- if let Some ( name) = name {
992- return self . call_intrinsic ( name, & [ val] ) ;
941+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
942+ return self . call_intrinsic (
943+ "llvm.wasm.trunc.unsigned" ,
944+ & [ dest_ty, src_ty] ,
945+ & [ val] ,
946+ ) ;
993947 }
994948 }
995949 }
@@ -1003,15 +957,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1003957 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1004958 let float_width = self . cx . float_width ( src_ty) ;
1005959 let int_width = self . cx . int_width ( dest_ty) ;
1006- let name = match ( int_width, float_width) {
1007- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.signed.i32.f32" ) ,
1008- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.signed.i32.f64" ) ,
1009- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.signed.i64.f32" ) ,
1010- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.signed.i64.f64" ) ,
1011- _ => None ,
1012- } ;
1013- if let Some ( name) = name {
1014- return self . call_intrinsic ( name, & [ val] ) ;
960+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
961+ return self . call_intrinsic (
962+ "llvm.wasm.trunc.signed" ,
963+ & [ dest_ty, src_ty] ,
964+ & [ val] ,
965+ ) ;
1015966 }
1016967 }
1017968 }
@@ -1084,22 +1035,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
10841035 return None ;
10851036 }
10861037
1087- let name = match ( ty. is_signed ( ) , ty. primitive_size ( self . tcx ) . bits ( ) ) {
1088- ( true , 8 ) => "llvm.scmp.i8.i8" ,
1089- ( true , 16 ) => "llvm.scmp.i8.i16" ,
1090- ( true , 32 ) => "llvm.scmp.i8.i32" ,
1091- ( true , 64 ) => "llvm.scmp.i8.i64" ,
1092- ( true , 128 ) => "llvm.scmp.i8.i128" ,
1093-
1094- ( false , 8 ) => "llvm.ucmp.i8.i8" ,
1095- ( false , 16 ) => "llvm.ucmp.i8.i16" ,
1096- ( false , 32 ) => "llvm.ucmp.i8.i32" ,
1097- ( false , 64 ) => "llvm.ucmp.i8.i64" ,
1098- ( false , 128 ) => "llvm.ucmp.i8.i128" ,
1038+ let size = ty. primitive_size ( self . tcx ) ;
1039+ let name = if ty. is_signed ( ) { "llvm.scmp" } else { "llvm.ucmp" } ;
10991040
1100- _ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
1101- } ;
1102- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1041+ Some ( self . call_intrinsic ( & name, & [ self . type_i8 ( ) , self . type_ix ( size. bits ( ) ) ] , & [ lhs, rhs] ) )
11031042 }
11041043
11051044 /* Miscellaneous instructions */
@@ -1385,11 +1324,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13851324 }
13861325
13871326 fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1388- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1327+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
13891328 }
13901329
13911330 fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1392- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1331+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
13931332 }
13941333
13951334 fn call (
@@ -1454,7 +1393,7 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
14541393 // Forward to the `get_static` method of `CodegenCx`
14551394 let global = self . cx ( ) . get_static ( def_id) ;
14561395 if self . cx ( ) . tcx . is_thread_local_static ( def_id) {
1457- let pointer = self . call_intrinsic ( "llvm.threadlocal.address" , & [ global] ) ;
1396+ let pointer = self . call_intrinsic ( "llvm.threadlocal.address" , & [ ] , & [ global] ) ;
14581397 // Cast to default address space if globals are in a different addrspace
14591398 self . pointercast ( pointer, self . type_ptr ( ) )
14601399 } else {
@@ -1649,8 +1588,13 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16491588}
16501589
16511590impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1652- pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1653- let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1591+ pub ( crate ) fn call_intrinsic (
1592+ & mut self ,
1593+ base_name : & str ,
1594+ type_params : & [ & ' ll Type ] ,
1595+ args : & [ & ' ll Value ] ,
1596+ ) -> & ' ll Value {
1597+ let ( ty, f) = self . cx . get_intrinsic ( base_name, type_params) ;
16541598 self . call ( ty, None , None , f, args, None , None )
16551599 }
16561600
@@ -1664,7 +1608,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16641608 return ;
16651609 }
16661610
1667- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1611+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
16681612 }
16691613}
16701614impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1689,31 +1633,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16891633 }
16901634}
16911635impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1692- fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1693- let src_ty = self . cx . val_ty ( val) ;
1694- let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
1695- assert_eq ! ( self . cx. vector_length( src_ty) , self . cx. vector_length( dest_ty) ) ;
1696- (
1697- self . cx . element_type ( src_ty) ,
1698- self . cx . element_type ( dest_ty) ,
1699- Some ( self . cx . vector_length ( src_ty) ) ,
1700- )
1701- } else {
1702- ( src_ty, dest_ty, None )
1703- } ;
1704- let float_width = self . cx . float_width ( float_ty) ;
1705- let int_width = self . cx . int_width ( int_ty) ;
1706-
1707- let instr = if signed { "fptosi" } else { "fptoui" } ;
1708- let name = if let Some ( vector_length) = vector_length {
1709- format ! ( "llvm.{instr}.sat.v{vector_length}i{int_width}.v{vector_length}f{float_width}" )
1710- } else {
1711- format ! ( "llvm.{instr}.sat.i{int_width}.f{float_width}" )
1712- } ;
1713- let f = self . declare_cfn ( & name, llvm:: UnnamedAddr :: No , self . type_func ( & [ src_ty] , dest_ty) ) ;
1714- self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
1715- }
1716-
17171636 pub ( crate ) fn landing_pad (
17181637 & mut self ,
17191638 ty : & ' ll Type ,
@@ -1819,7 +1738,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18191738 // llvm.type.test intrinsic. The LowerTypeTests link-time optimization pass replaces
18201739 // calls to this intrinsic with code to test type membership.
18211740 let typeid = self . get_metadata_value ( typeid_metadata) ;
1822- let cond = self . call_intrinsic ( "llvm.type.test" , & [ llfn, typeid] ) ;
1741+ let cond = self . call_intrinsic ( "llvm.type.test" , & [ ] , & [ llfn, typeid] ) ;
18231742 let bb_pass = self . append_sibling_block ( "type_test.pass" ) ;
18241743 let bb_fail = self . append_sibling_block ( "type_test.fail" ) ;
18251744 self . cond_br ( cond, bb_pass, bb_fail) ;
@@ -1887,7 +1806,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18871806 num_counters : & ' ll Value ,
18881807 index : & ' ll Value ,
18891808 ) {
1890- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1809+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
18911810 }
18921811
18931812 /// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1906,7 +1825,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19061825 hash : & ' ll Value ,
19071826 bitmap_bits : & ' ll Value ,
19081827 ) {
1909- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1828+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
19101829 }
19111830
19121831 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -1918,7 +1837,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19181837 mcdc_temp : & ' ll Value ,
19191838 ) {
19201839 let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1921- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1840+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
19221841 }
19231842
19241843 #[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments