Skip to content

Commit abcc631

Browse files
committed
change implementation of rust intrinsics to use the new api
1 parent 2bdff9e commit abcc631

File tree

8 files changed

+505
-1067
lines changed

8 files changed

+505
-1067
lines changed

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
897897
fn checked_binop(
898898
&mut self,
899899
oop: OverflowOp,
900-
typ: Ty<'_>,
900+
typ: Ty<'tcx>,
901901
lhs: Self::Value,
902902
rhs: Self::Value,
903903
) -> (Self::Value, Self::Value) {

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
405405
let actual_return_ty = self.llvm_return_type(cx);
406406
let actual_argument_tys = self.llvm_argument_types(cx);
407407

408-
if name.starts_with(b"llvm.")
409-
&& let Some((intrinsic, type_params)) = cx.parse_intrinsic_name(name)
410-
{
411-
let fn_ty = cx.intrinsic_type(intrinsic, &type_params);
408+
if name.starts_with(b"llvm.") {
409+
let Some((fn_ty, _)) = cx.get_intrinsic_from_name(name) else {
410+
todo!("Invalid LLVM intrinsic name `{}`", str::from_utf8(name).unwrap());
411+
};
412412

413413
let expected_return_ty = cx.get_return_type(fn_ty);
414414
let expected_argument_tys = cx.func_params_types(fn_ty);

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 98 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -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

16981637
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-
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
}
17171651
impl<'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
}
17381672
impl<'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

Comments
 (0)