@@ -484,73 +484,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
484484 fn checked_binop (
485485 & mut self ,
486486 oop : OverflowOp ,
487- ty : Ty < ' _ > ,
487+ ty : Ty < ' tcx > ,
488488 lhs : Self :: Value ,
489489 rhs : Self :: Value ,
490490 ) -> ( 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" ) ,
500- } ;
491+ let ( width, signed) = ty. int_size_and_signed ( self . tcx ) ;
501492
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- }
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+ }
533501
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- } ,
502+ let op = match oop {
503+ OverflowOp :: Add => "add" ,
504+ OverflowOp :: Sub => "sub" ,
505+ OverflowOp :: Mul => "mul" ,
551506 } ;
552507
553- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
508+ let llvm_intrinsic = format ! ( "llvm.{}{op}.with.overflow" , if signed { 's' } else { 'u' } ) ;
509+
510+ let res = self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width. bits ( ) ) ] , & [ 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,15 @@ 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" ,
1099-
1038+ let ( signed, llty) = match ty. kind ( ) {
1039+ ty:: Int ( t) => ( true , self . type_int_from_ty ( * t) ) ,
1040+ ty:: Uint ( t) => ( false , self . type_uint_from_ty ( * t) ) ,
1041+ ty:: Char => ( false , self . type_i32 ( ) ) ,
11001042 _ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
11011043 } ;
1102- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1044+
1045+ let llvm_intrinsic = format ! ( "llvm.{}cmp" , if signed { 's' } else { 'u' } ) ;
1046+ Some ( self . call_intrinsic ( & llvm_intrinsic, & [ self . type_i8 ( ) , llty] , & [ lhs, rhs] ) )
11031047 }
11041048
11051049 /* Miscellaneous instructions */
@@ -1385,11 +1329,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
13851329 }
13861330
13871331 fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1388- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1332+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
13891333 }
13901334
13911335 fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1392- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1336+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
13931337 }
13941338
13951339 fn call (
@@ -1640,14 +1584,41 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16401584 pub ( crate ) fn va_arg ( & mut self , list : & ' ll Value , ty : & ' ll Type ) -> & ' ll Value {
16411585 unsafe { llvm:: LLVMBuildVAArg ( self . llbuilder , list, ty, UNNAMED ) }
16421586 }
1643- }
16441587
1645- impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1646- pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1647- let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1648- self . call ( ty, None , None , f, args, None , None )
1588+ pub ( crate ) fn simple_call (
1589+ & mut self ,
1590+ fn_ty : & ' ll Type ,
1591+ llfn : & ' ll Value ,
1592+ args : & [ & ' ll Value ] ,
1593+ ) -> & ' ll Value {
1594+ let args = self . check_call ( "simple call" , fn_ty, llfn, args) ;
1595+
1596+ unsafe {
1597+ llvm:: LLVMBuildCall2 (
1598+ self . llbuilder ,
1599+ fn_ty,
1600+ llfn,
1601+ args. as_ptr ( ) ,
1602+ args. len ( ) as _ ,
1603+ c"" . as_ptr ( ) ,
1604+ )
1605+ }
1606+ }
1607+
1608+ pub ( crate ) fn call_intrinsic (
1609+ & mut self ,
1610+ base_name : & str ,
1611+ type_params : & [ & ' ll Type ] ,
1612+ args : & [ & ' ll Value ] ,
1613+ ) -> & ' ll Value {
1614+ let intrinsic = llvm:: Intrinsic :: lookup ( base_name. as_bytes ( ) )
1615+ . unwrap_or_else ( || bug ! ( "Intrinsic `{base_name}` not found" ) ) ;
1616+ let ( fn_ty, llfn) = self . cx . get_intrinsic ( intrinsic, type_params) ;
1617+ self . simple_call ( fn_ty, llfn, args)
16491618 }
1619+ }
16501620
1621+ impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
16511622 fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
16521623 let size = size. bytes ( ) ;
16531624 if size == 0 {
@@ -1658,7 +1629,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
16581629 return ;
16591630 }
16601631
1661- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1632+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
16621633 }
16631634}
16641635impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1683,29 +1654,24 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16831654 }
16841655}
16851656impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1686- fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1687- let src_ty = self . cx . val_ty ( val) ;
1688- let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
1689- assert_eq ! ( self . cx. vector_length( src_ty) , self . cx. vector_length( dest_ty) ) ;
1690- (
1691- self . cx . element_type ( src_ty) ,
1692- self . cx . element_type ( dest_ty) ,
1693- Some ( self . cx . vector_length ( src_ty) ) ,
1694- )
1695- } else {
1696- ( src_ty, dest_ty, None )
1657+ pub ( crate ) fn memcmp (
1658+ & mut self ,
1659+ ptr1 : & ' ll Value ,
1660+ ptr2 : & ' ll Value ,
1661+ num : & ' ll Value ,
1662+ ) -> & ' ll Value {
1663+ let llreturn_ty = match self . sess ( ) . target . arch . as_ref ( ) {
1664+ "avr" | "msp430" => self . type_i16 ( ) ,
1665+ _ => self . type_i32 ( ) ,
16971666 } ;
1698- let float_width = self . cx . float_width ( float_ty ) ;
1699- let int_width = self . cx . int_width ( int_ty ) ;
1667+ let fn_ty =
1668+ self . type_func ( & [ self . type_ptr ( ) , self . type_ptr ( ) , self . type_isize ( ) ] , llreturn_ty ) ;
17001669
1701- let instr = if signed { "fptosi" } else { "fptoui" } ;
1702- let name = if let Some ( vector_length) = vector_length {
1703- format ! ( "llvm.{instr}.sat.v{vector_length}i{int_width}.v{vector_length}f{float_width}" )
1704- } else {
1705- format ! ( "llvm.{instr}.sat.i{int_width}.f{float_width}" )
1706- } ;
1707- let f = self . declare_cfn ( & name, llvm:: UnnamedAddr :: No , self . type_func ( & [ src_ty] , dest_ty) ) ;
1708- self . call ( self . type_func ( & [ src_ty] , dest_ty) , None , None , f, & [ val] , None , None )
1670+ let llfn = self
1671+ . get_function ( "memcmp" )
1672+ . unwrap_or_else ( || self . declare_cfn ( "memcmp" , llvm:: UnnamedAddr :: No , fn_ty) ) ;
1673+
1674+ self . simple_call ( fn_ty, llfn, & [ ptr1, ptr2, num] )
17091675 }
17101676
17111677 pub ( crate ) fn landing_pad (
@@ -1878,7 +1844,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18781844 num_counters : & ' ll Value ,
18791845 index : & ' ll Value ,
18801846 ) {
1881- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1847+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
18821848 }
18831849
18841850 /// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1897,7 +1863,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18971863 hash : & ' ll Value ,
18981864 bitmap_bits : & ' ll Value ,
18991865 ) {
1900- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1866+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
19011867 }
19021868
19031869 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -1909,7 +1875,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19091875 mcdc_temp : & ' ll Value ,
19101876 ) {
19111877 let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1912- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1878+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
19131879 }
19141880
19151881 #[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments