@@ -14,7 +14,6 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
14
14
use rustc_codegen_ssa:: traits:: * ;
15
15
use rustc_data_structures:: small_c_str:: SmallCStr ;
16
16
use rustc_hir:: def_id:: DefId ;
17
- use rustc_middle:: bug;
18
17
use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
19
18
use rustc_middle:: ty:: layout:: {
20
19
FnAbiError , FnAbiOfHelpers , FnAbiRequest , HasTypingEnv , LayoutError , LayoutOfHelpers ,
@@ -484,73 +483,31 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
484
483
fn checked_binop (
485
484
& mut self ,
486
485
oop : OverflowOp ,
487
- ty : Ty < ' _ > ,
486
+ ty : Ty < ' tcx > ,
488
487
lhs : Self :: Value ,
489
488
rhs : Self :: Value ,
490
489
) -> ( 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" ,
500
506
} ;
501
507
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' } ) ;
552
509
553
- let res = self . call_intrinsic ( name, & [ lhs, rhs] ) ;
510
+ let res = self . call_intrinsic ( & name, & [ self . type_ix ( width ) ] , & [ lhs, rhs] ) ;
554
511
( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
555
512
}
556
513
@@ -954,11 +911,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
954
911
}
955
912
956
913
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 ] )
958
915
}
959
916
960
917
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 ] )
962
919
}
963
920
964
921
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> {
981
938
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
982
939
let float_width = self . cx . float_width ( src_ty) ;
983
940
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
+ ) ;
993
947
}
994
948
}
995
949
}
@@ -1003,15 +957,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1003
957
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1004
958
let float_width = self . cx . float_width ( src_ty) ;
1005
959
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
+ ) ;
1015
966
}
1016
967
}
1017
968
}
@@ -1084,22 +1035,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1084
1035
return None ;
1085
1036
}
1086
1037
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" } ;
1099
1040
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] ) )
1103
1042
}
1104
1043
1105
1044
/* Miscellaneous instructions */
@@ -1385,11 +1324,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1385
1324
}
1386
1325
1387
1326
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) ;
1389
1328
}
1390
1329
1391
1330
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) ;
1393
1332
}
1394
1333
1395
1334
fn call (
@@ -1454,7 +1393,7 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> {
1454
1393
// Forward to the `get_static` method of `CodegenCx`
1455
1394
let global = self . cx ( ) . get_static ( def_id) ;
1456
1395
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] ) ;
1458
1397
// Cast to default address space if globals are in a different addrspace
1459
1398
self . pointercast ( pointer, self . type_ptr ( ) )
1460
1399
} else {
@@ -1649,8 +1588,13 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1649
1588
}
1650
1589
1651
1590
impl < ' 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) ;
1654
1598
self . call ( ty, None , None , f, args, None , None )
1655
1599
}
1656
1600
@@ -1664,7 +1608,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1664
1608
return ;
1665
1609
}
1666
1610
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] ) ;
1668
1612
}
1669
1613
}
1670
1614
impl < ' 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> {
1689
1633
}
1690
1634
}
1691
1635
impl < ' 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
-
1717
1636
pub ( crate ) fn landing_pad (
1718
1637
& mut self ,
1719
1638
ty : & ' ll Type ,
@@ -1819,7 +1738,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1819
1738
// llvm.type.test intrinsic. The LowerTypeTests link-time optimization pass replaces
1820
1739
// calls to this intrinsic with code to test type membership.
1821
1740
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] ) ;
1823
1742
let bb_pass = self . append_sibling_block ( "type_test.pass" ) ;
1824
1743
let bb_fail = self . append_sibling_block ( "type_test.fail" ) ;
1825
1744
self . cond_br ( cond, bb_pass, bb_fail) ;
@@ -1887,7 +1806,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1887
1806
num_counters : & ' ll Value ,
1888
1807
index : & ' ll Value ,
1889
1808
) {
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] ) ;
1891
1810
}
1892
1811
1893
1812
/// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1906,7 +1825,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1906
1825
hash : & ' ll Value ,
1907
1826
bitmap_bits : & ' ll Value ,
1908
1827
) {
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] ) ;
1910
1829
}
1911
1830
1912
1831
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -1918,7 +1837,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1918
1837
mcdc_temp : & ' ll Value ,
1919
1838
) {
1920
1839
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) ;
1922
1841
}
1923
1842
1924
1843
#[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments