@@ -67,7 +67,6 @@ impl<'a, 'll> SBuilder<'a, 'll> {
67
67
) -> & ' ll Value {
68
68
debug ! ( "call {:?} with args ({:?})" , llfn, args) ;
69
69
70
- let args = self . cast_arguments ( "call" , llty, llfn, args) ;
71
70
let funclet_bundle = funclet. map ( |funclet| funclet. bundle ( ) ) ;
72
71
let mut bundles: SmallVec < [ _ ; 2 ] > = SmallVec :: new ( ) ;
73
72
if let Some ( funclet_bundle) = funclet_bundle {
@@ -105,21 +104,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
105
104
let vector_type = self . cx . val_ty ( val) ;
106
105
107
106
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] )
123
108
}
124
109
125
110
pub ( crate ) fn cast_tile_to_vector (
@@ -130,20 +115,7 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
130
115
assert ! ( self . cx. val_ty( val) == self . cx. type_x86amx( ) ) ;
131
116
assert ! ( self . cx. type_kind( vector_type) == TypeKind :: Vector ) ;
132
117
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] )
147
119
}
148
120
149
121
pub ( crate ) fn ret_void ( & mut self ) {
@@ -546,58 +518,32 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
546
518
_ => panic ! ( "tried to get overflow intrinsic for op applied to non-int type" ) ,
547
519
} ;
548
520
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
+ } ;
580
526
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" ,
598
542
} ;
599
543
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] ) ;
601
547
( self . extract_value ( res, 0 ) , self . extract_value ( res, 1 ) )
602
548
}
603
549
@@ -1028,15 +974,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1028
974
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1029
975
let float_width = self . cx . float_width ( src_ty) ;
1030
976
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
+ ) ;
1040
983
}
1041
984
}
1042
985
}
@@ -1050,15 +993,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1050
993
if self . cx . type_kind ( src_ty) != TypeKind :: Vector {
1051
994
let float_width = self . cx . float_width ( src_ty) ;
1052
995
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
+ ) ;
1062
1002
}
1063
1003
}
1064
1004
}
@@ -1131,22 +1071,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1131
1071
return None ;
1132
1072
}
1133
1073
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] ) )
1150
1077
}
1151
1078
1152
1079
/* Miscellaneous instructions */
@@ -1432,11 +1359,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
1432
1359
}
1433
1360
1434
1361
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) ;
1436
1363
}
1437
1364
1438
1365
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) ;
1440
1367
}
1441
1368
1442
1369
fn call (
@@ -1645,6 +1572,29 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1645
1572
ret. expect ( "LLVM does not have support for catchret" )
1646
1573
}
1647
1574
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
+
1648
1598
fn cast_arguments < ' b > (
1649
1599
& mut self ,
1650
1600
typ : & str ,
@@ -1696,11 +1646,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
1696
1646
}
1697
1647
1698
1648
impl < ' 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
-
1704
1649
fn call_lifetime_intrinsic ( & mut self , intrinsic : & str , ptr : & ' ll Value , size : Size ) {
1705
1650
let size = size. bytes ( ) ;
1706
1651
if size == 0 {
@@ -1711,7 +1656,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1711
1656
return ;
1712
1657
}
1713
1658
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] ) ;
1715
1660
}
1716
1661
}
1717
1662
impl < ' 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> {
1736
1681
}
1737
1682
}
1738
1683
impl < ' 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
+
1739
1715
fn fptoint_sat ( & mut self , signed : bool , val : & ' ll Value , dest_ty : & ' ll Type ) -> & ' ll Value {
1740
1716
let src_ty = self . cx . val_ty ( val) ;
1741
1717
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> {
1958
1934
num_counters : & ' ll Value ,
1959
1935
index : & ' ll Value ,
1960
1936
) {
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] ) ;
1962
1938
}
1963
1939
1964
1940
/// Emits a call to `llvm.instrprof.mcdc.parameters`.
@@ -1977,7 +1953,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1977
1953
hash : & ' ll Value ,
1978
1954
bitmap_bits : & ' ll Value ,
1979
1955
) {
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] ) ;
1981
1957
}
1982
1958
1983
1959
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -1989,7 +1965,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
1989
1965
mcdc_temp : & ' ll Value ,
1990
1966
) {
1991
1967
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) ;
1993
1969
}
1994
1970
1995
1971
#[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments