@@ -67,7 +67,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
6767 ) -> & ' ll Value {
6868 debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
6969
70- let args = self . cast_arguments ( "call" , llty, llfn, args) ;
7170 let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
7271 let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
7372 if let Some ( funclet_bundle) = funclet_bundle {
@@ -105,21 +104,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
105104 let vector_type = self . cx . val_ty ( val) ;
106105
107106 assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
108-
109- let intrinsic = llvm:: Intrinsic :: lookup ( b"llvm.x86.cast.vector.to.tile" . as_ref ( ) ) . unwrap ( ) ;
110- let ( fn_ty, f) = self . cx . get_or_declare_intrinsic ( intrinsic, & [ vector_type] ) ;
111- unsafe {
112- llvm:: LLVMBuildCallWithOperandBundles (
113- self . llbuilder ,
114- fn_ty,
115- f,
116- [ val] . as_ptr ( ) . cast ( ) ,
117- 1 ,
118- [ ] . as_ptr ( ) ,
119- 0 ,
120- c"" . as_ptr ( ) ,
121- )
122- }
107+ self . call_intrinsic ( "llvm.x86.cast.vector.to.tile" , & [ vector_type] , & [ val] )
123108 }
124109
125110 pub ( crate ) fn cast_tile_to_vector (
@@ -130,20 +115,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
130115 assert ! ( self . cx. val_ty( val) == self . cx. type_x86amx( ) ) ;
131116 assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
132117
133- let intrinsic = llvm:: Intrinsic :: lookup ( b"llvm.x86.cast.tile.to.vector" ) . unwrap ( ) ;
134- let ( fn_ty, f) = self . cx . get_or_declare_intrinsic ( intrinsic, & [ vector_type] ) ;
135- unsafe {
136- llvm:: LLVMBuildCallWithOperandBundles (
137- self . llbuilder ,
138- fn_ty,
139- f,
140- [ val] . as_ptr ( ) . cast ( ) ,
141- 1 ,
142- [ ] . as_ptr ( ) ,
143- 0 ,
144- c"" . as_ptr ( ) ,
145- )
146- }
118+ self . call_intrinsic ( "llvm.x86.cast.tile.to.vector" , & [ vector_type] , & [ val] )
147119 }
148120
149121 pub ( crate ) fn ret_void ( & mut self ) {
@@ -546,58 +518,32 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
546518 _ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
547519 } ;
548520
549- let name = match oop {
550- OverflowOp :: Add => match new_kind {
551- Int ( I8 ) => "llvm.sadd.with.overflow.i8" ,
552- Int ( I16 ) => "llvm.sadd.with.overflow.i16" ,
553- Int ( I32 ) => "llvm.sadd.with.overflow.i32" ,
554- Int ( I64 ) => "llvm.sadd.with.overflow.i64" ,
555- Int ( I128 ) => "llvm.sadd.with.overflow.i128" ,
556-
557- Uint ( U8 ) => "llvm.uadd.with.overflow.i8" ,
558- Uint ( U16 ) => "llvm.uadd.with.overflow.i16" ,
559- Uint ( U32 ) => "llvm.uadd.with.overflow.i32" ,
560- Uint ( U64 ) => "llvm.uadd.with.overflow.i64" ,
561- Uint ( U128 ) => "llvm.uadd.with.overflow.i128" ,
562-
563- _ => unreachable ! ( ) ,
564- } ,
565- OverflowOp :: Sub => match new_kind {
566- Int ( I8 ) => "llvm.ssub.with.overflow.i8" ,
567- Int ( I16 ) => "llvm.ssub.with.overflow.i16" ,
568- Int ( I32 ) => "llvm.ssub.with.overflow.i32" ,
569- Int ( I64 ) => "llvm.ssub.with.overflow.i64" ,
570- Int ( I128 ) => "llvm.ssub.with.overflow.i128" ,
571-
572- Uint ( _) => {
573- // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
574- // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
575- // in the backend if profitable.
576- let sub = self . sub ( lhs, rhs) ;
577- let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
578- return ( sub, cmp) ;
579- }
521+ let ( signed, width) = match new_kind {
522+ Int ( t) => ( true , t. bit_width ( ) . unwrap ( ) ) ,
523+ Uint ( t) => ( false , t. bit_width ( ) . unwrap ( ) ) ,
524+ _ => unreachable ! ( ) ,
525+ } ;
580526
581- _ => unreachable ! ( ) ,
582- } ,
583- OverflowOp :: Mul => match new_kind {
584- Int ( I8 ) => "llvm.smul.with.overflow.i8" ,
585- Int ( I16 ) => "llvm.smul.with.overflow.i16" ,
586- Int ( I32 ) => "llvm.smul.with.overflow.i32" ,
587- Int ( I64 ) => "llvm.smul.with.overflow.i64" ,
588- Int ( I128 ) => "llvm.smul.with.overflow.i128" ,
589-
590- Uint ( U8 ) => "llvm.umul.with.overflow.i8" ,
591- Uint ( U16 ) => "llvm.umul.with.overflow.i16" ,
592- Uint ( U32 ) => "llvm.umul.with.overflow.i32" ,
593- Uint ( U64 ) => "llvm.umul.with.overflow.i64" ,
594- Uint ( U128 ) => "llvm.umul.with.overflow.i128" ,
595-
596- _ => unreachable ! ( ) ,
597- } ,
527+ if let OverflowOp :: Sub = oop
528+ && !signed
529+ {
530+ // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
531+ // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
532+ // in the backend if profitable.
533+ let sub = self . sub ( lhs, rhs) ;
534+ let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
535+ return ( sub, cmp) ;
536+ }
537+
538+ let op = match oop {
539+ OverflowOp :: Add => "add" ,
540+ OverflowOp :: Sub => "sub" ,
541+ OverflowOp :: Mul => "mul" ,
598542 } ;
599543
600- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
544+ let llvm_intrinsic = format ! ( "llvm.{}{}.with.overflow" , if signed { 's' } else { 'u' } , op) ;
545+
546+ let res = self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width) ] , & [ lhs, rhs] ) ;
601547 ( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
602548 }
603549
@@ -1028,15 +974,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1028974 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1029975 let float_width = self . cx . float_width ( src_ty) ;
1030976 let int_width = self . cx . int_width ( dest_ty) ;
1031- let name = match ( int_width, float_width) {
1032- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f32" ) ,
1033- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i32.f64" ) ,
1034- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f32" ) ,
1035- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.unsigned.i64.f64" ) ,
1036- _ => None ,
1037- } ;
1038- if let Some ( name) = name {
1039- return self . call_intrinsic ( name, & [ val] ) ;
977+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
978+ return self . call_intrinsic (
979+ "llvm.wasm.trunc.unsigned" ,
980+ & [ dest_ty, src_ty] ,
981+ & [ val] ,
982+ ) ;
1040983 }
1041984 }
1042985 }
@@ -1050,15 +993,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1050993 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1051994 let float_width = self . cx . float_width ( src_ty) ;
1052995 let int_width = self . cx . int_width ( dest_ty) ;
1053- let name = match ( int_width, float_width) {
1054- ( 32 , 32 ) => Some ( "llvm.wasm.trunc.signed.i32.f32" ) ,
1055- ( 32 , 64 ) => Some ( "llvm.wasm.trunc.signed.i32.f64" ) ,
1056- ( 64 , 32 ) => Some ( "llvm.wasm.trunc.signed.i64.f32" ) ,
1057- ( 64 , 64 ) => Some ( "llvm.wasm.trunc.signed.i64.f64" ) ,
1058- _ => None ,
1059- } ;
1060- if let Some ( name) = name {
1061- return self . call_intrinsic ( name, & [ val] ) ;
996+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
997+ return self . call_intrinsic (
998+ "llvm.wasm.trunc.signed" ,
999+ & [ dest_ty, src_ty] ,
1000+ & [ val] ,
1001+ ) ;
10621002 }
10631003 }
10641004 }
@@ -1131,22 +1071,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11311071 return None ;
11321072 }
11331073
1134- let name = match ( ty. is_signed ( ) , ty. primitive_size ( self . tcx ) . bits ( ) ) {
1135- ( true , 8 ) => "llvm.scmp.i8.i8" ,
1136- ( true , 16 ) => "llvm.scmp.i8.i16" ,
1137- ( true , 32 ) => "llvm.scmp.i8.i32" ,
1138- ( true , 64 ) => "llvm.scmp.i8.i64" ,
1139- ( true , 128 ) => "llvm.scmp.i8.i128" ,
1140-
1141- ( false , 8 ) => "llvm.ucmp.i8.i8" ,
1142- ( false , 16 ) => "llvm.ucmp.i8.i16" ,
1143- ( false , 32 ) => "llvm.ucmp.i8.i32" ,
1144- ( false , 64 ) => "llvm.ucmp.i8.i64" ,
1145- ( false , 128 ) => "llvm.ucmp.i8.i128" ,
1146-
1147- _ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
1148- } ;
1149- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1074+ let ( width, signed) = ty. int_size_and_signed ( self . tcx ) ;
1075+ let llvm_intrinsic = format ! ( "llvm.{}cmp" , if signed { 's' } else { 'u' } ) ;
1076+ Some ( self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width. bits ( ) ) ] , & [ lhs, rhs] ) )
11501077 }
11511078
11521079 /* Miscellaneous instructions */
@@ -1432,11 +1359,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14321359 }
14331360
14341361 fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1435- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1362+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
14361363 }
14371364
14381365 fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1439- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1366+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
14401367 }
14411368
14421369 fn call (
@@ -1645,6 +1572,29 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16451572 ret. expect ( "LLVM does not have support for catchret" )
16461573 }
16471574
1575+ pub ( crate ) fn call_intrinsic (
1576+ & mut self ,
1577+ base_name : & str ,
1578+ type_params : & [ & ' ll Type ] ,
1579+ args : & [ & ' ll Value ] ,
1580+ ) -> & ' ll Value {
1581+ let intrinsic = llvm:: Intrinsic :: lookup ( base_name. as_bytes ( ) )
1582+ . unwrap_or_else ( || bug ! ( "Intrinsic `{base_name}` not found" ) ) ;
1583+ let ( fn_ty, llfn) = self . cx . get_intrinsic ( intrinsic, type_params) ;
1584+ unsafe {
1585+ llvm:: LLVMBuildCallWithOperandBundles (
1586+ self . llbuilder ,
1587+ fn_ty,
1588+ llfn,
1589+ args. as_ptr ( ) ,
1590+ args. len ( ) . try_into ( ) . unwrap ( ) ,
1591+ [ ] . as_ptr ( ) ,
1592+ 0 ,
1593+ c"" . as_ptr ( ) ,
1594+ )
1595+ }
1596+ }
1597+
16481598 fn cast_arguments < ' b > (
16491599 & mut self ,
16501600 typ : & str ,
@@ -1696,11 +1646,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16961646}
16971647
16981648impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1699- pub ( crate ) fn call_intrinsic ( & mut self , intrinsic : & str , args : & [ & ' ll Value ] ) -> & ' ll Value {
1700- let ( ty, f) = self . cx . get_intrinsic ( intrinsic) ;
1701- self . call ( ty, None , None , f, args, None , None )
1702- }
1703-
17041649 fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
17051650 let size = size. bytes ( ) ;
17061651 if size == 0 {
@@ -1711,7 +1656,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17111656 return ;
17121657 }
17131658
1714- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1659+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
17151660 }
17161661}
17171662impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1736,6 +1681,37 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17361681 }
17371682}
17381683impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1684+ pub ( crate ) fn memcmp (
1685+ & mut self ,
1686+ ptr1 : & ' ll Value ,
1687+ ptr2 : & ' ll Value ,
1688+ num : & ' ll Value ,
1689+ ) -> & ' ll Value {
1690+ let llreturn_ty = match self . sess ( ) . target . arch . as_ref ( ) {
1691+ "avr" | "msp430" => self . type_i16 ( ) ,
1692+ _ => self . type_i32 ( ) ,
1693+ } ;
1694+ let fn_ty =
1695+ self . type_func ( & [ self . type_ptr ( ) , self . type_ptr ( ) , self . type_isize ( ) ] , llreturn_ty) ;
1696+
1697+ let llfn = self
1698+ . get_function ( "memcmp" )
1699+ . unwrap_or_else ( || self . declare_cfn ( "memcmp" , llvm:: UnnamedAddr :: No , fn_ty) ) ;
1700+
1701+ unsafe {
1702+ llvm:: LLVMBuildCallWithOperandBundles (
1703+ self . llbuilder ,
1704+ fn_ty,
1705+ llfn,
1706+ [ ptr1, ptr2, num] . as_ptr ( ) ,
1707+ 3 ,
1708+ [ ] . as_ptr ( ) ,
1709+ 0 ,
1710+ c"" . as_ptr ( ) ,
1711+ )
1712+ }
1713+ }
1714+
17391715 fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
17401716 let src_ty = self . cx . val_ty ( val) ;
17411717 let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
@@ -1958,7 +1934,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19581934 num_counters : & ' ll Value ,
19591935 index : & ' ll Value ,
19601936 ) {
1961- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1937+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
19621938 }
19631939
19641940 /// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1977,7 +1953,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19771953 hash : & ' ll Value ,
19781954 bitmap_bits : & ' ll Value ,
19791955 ) {
1980- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1956+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
19811957 }
19821958
19831959 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -1989,7 +1965,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19891965 mcdc_temp : & ' ll Value ,
19901966 ) {
19911967 let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1992- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1968+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
19931969 }
19941970
19951971 #[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments