@@ -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 ) {
@@ -531,73 +503,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
531503 fn checked_binop (
532504 & mut self ,
533505 oop : OverflowOp ,
534- ty : Ty < ' _ > ,
506+ ty : Ty < ' tcx > ,
535507 lhs : Self :: Value ,
536508 rhs : Self :: Value ,
537509 ) -> ( Self :: Value , Self :: Value ) {
538- use rustc_middle:: ty:: IntTy :: * ;
539- use rustc_middle:: ty:: UintTy :: * ;
540- use rustc_middle:: ty:: { Int , Uint } ;
541-
542- let new_kind = match ty. kind ( ) {
543- Int ( t @ Isize ) => Int ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
544- Uint ( t @ Usize ) => Uint ( t. normalize ( self . tcx . sess . target . pointer_width ) ) ,
545- t @ ( Uint ( _) | Int ( _) ) => * t,
546- _ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
547- } ;
510+ let ( width, signed) = ty. int_size_and_signed ( self . tcx ) ;
548511
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- }
512+ if oop == OverflowOp :: Sub && !signed {
513+ // Emit sub and icmp instead of llvm.usub.with.overflow. LLVM considers these
514+ // to be the canonical form. It will attempt to reform llvm.usub.with.overflow
515+ // in the backend if profitable.
516+ let sub = self . sub ( lhs, rhs) ;
517+ let cmp = self . icmp ( IntPredicate :: IntULT , lhs, rhs) ;
518+ return ( sub, cmp) ;
519+ }
580520
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- } ,
521+ let op = match oop {
522+ OverflowOp :: Add => "add" ,
523+ OverflowOp :: Sub => "sub" ,
524+ OverflowOp :: Mul => "mul" ,
598525 } ;
599526
600- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
527+ let llvm_intrinsic = format ! ( "llvm.{}{op}.with.overflow" , if signed { 's' } else { 'u' } ) ;
528+
529+ let res = self . call_intrinsic ( & llvm_intrinsic, & [ self . type_ix ( width. bits ( ) ) ] , & [ lhs, rhs] ) ;
601530 ( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
602531 }
603532
@@ -1028,15 +957,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1028957 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1029958 let float_width = self . cx . float_width ( src_ty) ;
1030959 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] ) ;
960+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
961+ return self . call_intrinsic (
962+ "llvm.wasm.trunc.unsigned" ,
963+ & [ dest_ty, src_ty] ,
964+ & [ val] ,
965+ ) ;
1040966 }
1041967 }
1042968 }
@@ -1050,15 +976,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1050976 if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1051977 let float_width = self . cx . float_width ( src_ty) ;
1052978 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] ) ;
979+ if matches ! ( ( int_width, float_width) , ( 32 | 64 , 32 | 64 ) ) {
980+ return self . call_intrinsic (
981+ "llvm.wasm.trunc.signed" ,
982+ & [ dest_ty, src_ty] ,
983+ & [ val] ,
984+ ) ;
1062985 }
1063986 }
1064987 }
@@ -1131,22 +1054,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11311054 return None ;
11321055 }
11331056
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-
1057+ let ( signed, llty) = match ty. kind ( ) {
1058+ ty:: Int ( t) => ( true , self . type_int_from_ty ( * t) ) ,
1059+ ty:: Uint ( t) => ( true , self . type_uint_from_ty ( * t) ) ,
1060+ ty:: Char => ( true , self . type_i32 ( ) ) ,
11471061 _ => bug ! ( "three-way compare unsupported for type {ty:?}" ) ,
11481062 } ;
1149- Some ( self . call_intrinsic ( name, & [ lhs, rhs] ) )
1063+
1064+ let llvm_intrinsic = format ! ( "llvm.{}cmp" , if signed { 's' } else { 'u' } ) ;
1065+ Some ( self . call_intrinsic ( & llvm_intrinsic, & [ self . type_i8 ( ) , llty] , & [ lhs, rhs] ) )
11501066 }
11511067
11521068 /* Miscellaneous instructions */
@@ -1432,11 +1348,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14321348 }
14331349
14341350 fn lifetime_start ( & mut self , ptr : & ' ll Value , size : Size ) {
1435- self . call_lifetime_intrinsic ( "llvm.lifetime.start.p0i8 " , ptr, size) ;
1351+ self . call_lifetime_intrinsic ( "llvm.lifetime.start" , ptr, size) ;
14361352 }
14371353
14381354 fn lifetime_end ( & mut self , ptr : & ' ll Value , size : Size ) {
1439- self . call_lifetime_intrinsic ( "llvm.lifetime.end.p0i8 " , ptr, size) ;
1355+ self . call_lifetime_intrinsic ( "llvm.lifetime.end" , ptr, size) ;
14401356 }
14411357
14421358 fn call (
@@ -1645,6 +1561,29 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16451561 ret. expect ( "LLVM does not have support for catchret" )
16461562 }
16471563
1564+ pub ( crate ) fn call_intrinsic (
1565+ & mut self ,
1566+ base_name : & str ,
1567+ type_params : & [ & ' ll Type ] ,
1568+ args : & [ & ' ll Value ] ,
1569+ ) -> & ' ll Value {
1570+ let intrinsic = llvm:: Intrinsic :: lookup ( base_name. as_bytes ( ) )
1571+ . unwrap_or_else ( || bug ! ( "Intrinsic `{base_name}` not found" ) ) ;
1572+ let ( fn_ty, llfn) = self . cx . get_intrinsic ( intrinsic, type_params) ;
1573+ unsafe {
1574+ llvm:: LLVMBuildCallWithOperandBundles (
1575+ self . llbuilder ,
1576+ fn_ty,
1577+ llfn,
1578+ args. as_ptr ( ) ,
1579+ args. len ( ) . try_into ( ) . unwrap ( ) ,
1580+ [ ] . as_ptr ( ) ,
1581+ 0 ,
1582+ c"" . as_ptr ( ) ,
1583+ )
1584+ }
1585+ }
1586+
16481587 fn cast_arguments < ' b > (
16491588 & mut self ,
16501589 typ : & str ,
@@ -1696,11 +1635,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16961635}
16971636
16981637impl < ' 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-
17041638 fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
17051639 let size = size. bytes ( ) ;
17061640 if size == 0 {
@@ -1711,7 +1645,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17111645 return ;
17121646 }
17131647
1714- self . call_intrinsic ( intrinsic, & [ self . cx . const_u64 ( size) , ptr] ) ;
1648+ self . call_intrinsic ( intrinsic, & [ self . type_ptr ( ) ] , & [ self . cx . const_u64 ( size) , ptr] ) ;
17151649 }
17161650}
17171651impl < ' a , ' ll , CX : Borrow < SCx < ' ll > > > GenericBuilder < ' a , ' ll , CX > {
@@ -1736,6 +1670,37 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
17361670 }
17371671}
17381672impl < ' a , ' ll , ' tcx > Builder < ' a , ' ll , ' tcx > {
1673+ pub ( crate ) fn memcmp (
1674+ & mut self ,
1675+ ptr1 : & ' ll Value ,
1676+ ptr2 : & ' ll Value ,
1677+ num : & ' ll Value ,
1678+ ) -> & ' ll Value {
1679+ let llreturn_ty = match self . sess ( ) . target . arch . as_ref ( ) {
1680+ "avr" | "msp430" => self . type_i16 ( ) ,
1681+ _ => self . type_i32 ( ) ,
1682+ } ;
1683+ let fn_ty =
1684+ self . type_func ( & [ self . type_ptr ( ) , self . type_ptr ( ) , self . type_isize ( ) ] , llreturn_ty) ;
1685+
1686+ let llfn = self
1687+ . get_function ( "memcmp" )
1688+ . unwrap_or_else ( || self . declare_cfn ( "memcmp" , llvm:: UnnamedAddr :: No , fn_ty) ) ;
1689+
1690+ unsafe {
1691+ llvm:: LLVMBuildCallWithOperandBundles (
1692+ self . llbuilder ,
1693+ fn_ty,
1694+ llfn,
1695+ [ ptr1, ptr2, num] . as_ptr ( ) ,
1696+ 3 ,
1697+ [ ] . as_ptr ( ) ,
1698+ 0 ,
1699+ c"" . as_ptr ( ) ,
1700+ )
1701+ }
1702+ }
1703+
17391704 fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
17401705 let src_ty = self . cx . val_ty ( val) ;
17411706 let ( float_ty, int_ty, vector_length) = if self . cx . type_kind ( src_ty) == TypeKind :: Vector {
@@ -1958,7 +1923,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19581923 num_counters : & ' ll Value ,
19591924 index : & ' ll Value ,
19601925 ) {
1961- self . call_intrinsic ( "llvm.instrprof.increment" , & [ fn_name, hash, num_counters, index] ) ;
1926+ self . call_intrinsic ( "llvm.instrprof.increment" , & [ ] , & [ fn_name, hash, num_counters, index] ) ;
19621927 }
19631928
19641929 /// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1977,7 +1942,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19771942 hash : & ' ll Value ,
19781943 bitmap_bits : & ' ll Value ,
19791944 ) {
1980- self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ fn_name, hash, bitmap_bits] ) ;
1945+ self . call_intrinsic ( "llvm.instrprof.mcdc.parameters" , & [ ] , & [ fn_name, hash, bitmap_bits] ) ;
19811946 }
19821947
19831948 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -1989,7 +1954,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
19891954 mcdc_temp : & ' ll Value ,
19901955 ) {
19911956 let args = & [ fn_name, hash, bitmap_index, mcdc_temp] ;
1992- self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , args) ;
1957+ self . call_intrinsic ( "llvm.instrprof.mcdc.tvbitmap.update" , & [ ] , args) ;
19931958 }
19941959
19951960 #[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments