Skip to content

Commit efc6941

Browse files
committed
Simplify and dedup intrinsic call logic
1 parent 5cdd696 commit efc6941

File tree

6 files changed

+58
-109
lines changed

6 files changed

+58
-109
lines changed

compiler/rustc_codegen_llvm/src/allocator.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ fn create_wrapper_function(
107107
let ty = cx.type_func(args, output.unwrap_or_else(|| cx.type_void()));
108108
let llfn = declare_simple_fn(
109109
&cx,
110-
from_name,
110+
from_name.as_bytes(),
111111
llvm::CallConv::CCallConv,
112112
llvm::UnnamedAddr::Global,
113113
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
@@ -130,7 +130,7 @@ fn create_wrapper_function(
130130

131131
let callee = declare_simple_fn(
132132
&cx,
133-
to_name,
133+
to_name.as_bytes(),
134134
llvm::CallConv::CCallConv,
135135
llvm::UnnamedAddr::Global,
136136
llvm::Visibility::Hidden,
@@ -150,7 +150,7 @@ fn create_wrapper_function(
150150
.enumerate()
151151
.map(|(i, _)| llvm::get_param(llfn, i as c_uint))
152152
.collect::<Vec<_>>();
153-
let ret = bx.call(ty, callee, &args, None);
153+
let ret = bx.simple_call(ty, callee, &args, None);
154154
llvm::LLVMSetTailCall(ret, True);
155155
if output.is_some() {
156156
bx.ret(ret);

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ use tracing::{debug, instrument, warn};
3131

3232
use crate::abi::FnAbiLlvmExt;
3333
use crate::attributes;
34-
use crate::common::{AsCCharPtr, Funclet};
34+
use crate::common::Funclet;
3535
use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
36+
use crate::declare::declare_simple_fn;
3637
use crate::llvm::{
3738
self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
3839
};
@@ -57,39 +58,6 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> {
5758
}
5859
}
5960

60-
impl<'a, 'll> SBuilder<'a, 'll> {
61-
pub(crate) fn call(
62-
&mut self,
63-
llty: &'ll Type,
64-
llfn: &'ll Value,
65-
args: &[&'ll Value],
66-
funclet: Option<&Funclet<'ll>>,
67-
) -> &'ll Value {
68-
debug!("call {:?} with args ({:?})", llfn, args);
69-
70-
let args = self.cast_arguments("call", llty, llfn, args, false);
71-
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
72-
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
73-
if let Some(funclet_bundle) = funclet_bundle {
74-
bundles.push(funclet_bundle);
75-
}
76-
77-
let call = unsafe {
78-
llvm::LLVMBuildCallWithOperandBundles(
79-
self.llbuilder,
80-
llty,
81-
llfn,
82-
args.as_ptr(),
83-
args.len() as c_uint,
84-
bundles.as_ptr(),
85-
bundles.len() as c_uint,
86-
c"".as_ptr(),
87-
)
88-
};
89-
call
90-
}
91-
}
92-
9361
impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
9462
fn with_cx(scx: &'a GenericCx<'ll, CX>) -> Self {
9563
// Create a fresh builder from the simple context.
@@ -1610,31 +1578,33 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16101578

16111579
pub(crate) fn simple_call(
16121580
&mut self,
1613-
name: &[u8],
1614-
fn_ty: &'ll Type,
1581+
llty: &'ll Type,
1582+
llfn: &'ll Value,
16151583
args: &[&'ll Value],
1584+
funclet: Option<&Funclet<'ll>>,
16161585
) -> &'ll Value {
1617-
let llfn = unsafe {
1618-
llvm::LLVMRustGetOrInsertFunction(
1619-
self.cx.llmod(),
1620-
name.as_c_char_ptr(),
1621-
name.len(),
1622-
fn_ty,
1623-
)
1624-
};
1586+
debug!("simple_call {:?} with args ({:?})", llfn, args);
16251587

1626-
let args = self.cast_arguments("simple_call", fn_ty, llfn, args, false);
1588+
let args = self.cast_arguments("simple_call", llty, llfn, args, false);
1589+
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
1590+
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
1591+
if let Some(funclet_bundle) = funclet_bundle {
1592+
bundles.push(funclet_bundle);
1593+
}
16271594

1628-
unsafe {
1629-
llvm::LLVMBuildCall2(
1595+
let call = unsafe {
1596+
llvm::LLVMBuildCallWithOperandBundles(
16301597
self.llbuilder,
1631-
fn_ty,
1598+
llty,
16321599
llfn,
16331600
args.as_ptr(),
1634-
args.len() as _,
1601+
args.len() as c_uint,
1602+
bundles.as_ptr(),
1603+
bundles.len() as c_uint,
16351604
c"".as_ptr(),
16361605
)
1637-
}
1606+
};
1607+
call
16381608
}
16391609

16401610
pub(crate) fn call_intrinsic(
@@ -1651,13 +1621,23 @@ impl<'a, 'll, CX: Borrow<SCx<'ll>>> GenericBuilder<'a, 'll, CX> {
16511621
let fn_ty = self.cx.intrinsic_type(intrinsic, type_params);
16521622

16531623
let full_name = if intrinsic.is_overloaded() {
1624+
assert!(!type_params.is_empty());
16541625
&intrinsic.overloaded_name(self.cx.llmod(), type_params)
16551626
} else {
16561627
assert!(type_params.is_empty());
16571628
base_name.as_bytes()
16581629
};
16591630

1660-
self.simple_call(full_name, fn_ty, args)
1631+
let llfn = declare_simple_fn(
1632+
self.cx,
1633+
full_name,
1634+
llvm::CCallConv,
1635+
llvm::UnnamedAddr::No,
1636+
llvm::Visibility::Default,
1637+
fn_ty,
1638+
);
1639+
1640+
self.simple_call(fn_ty, llfn, args, None)
16611641
}
16621642
}
16631643

@@ -1710,7 +1690,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17101690
let fn_ty =
17111691
self.type_func(&[self.type_ptr(), self.type_ptr(), self.type_isize()], llreturn_ty);
17121692

1713-
self.simple_call(b"memcmp", fn_ty, &[ptr1, ptr2, num])
1693+
let llfn = self.declare_cfn("memcmp", llvm::UnnamedAddr::No, fn_ty);
1694+
1695+
self.simple_call(fn_ty, llfn, &[ptr1, ptr2, num], None)
17141696
}
17151697

17161698
fn cast_return(

compiler/rustc_codegen_llvm/src/builder/autodiff.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -296,18 +296,17 @@ fn generate_enzyme_call<'ll>(
296296
attrs: AutoDiffAttrs,
297297
) {
298298
// We have to pick the name depending on whether we want forward or reverse mode autodiff.
299-
let mut ad_name: String = match attrs.mode {
300-
DiffMode::Forward => "__enzyme_fwddiff",
301-
DiffMode::Reverse => "__enzyme_autodiff",
299+
let mut ad_name = match attrs.mode {
300+
DiffMode::Forward => b"__enzyme_fwddiff".as_slice(),
301+
DiffMode::Reverse => b"__enzyme_autodiff",
302302
_ => panic!("logic bug in autodiff, unrecognized mode"),
303303
}
304-
.to_string();
304+
.to_vec();
305305

306306
// add outer_fn name to ad_name to make it unique, in case users apply autodiff to multiple
307-
// functions. Unwrap will only panic, if LLVM gave us an invalid string.
308-
let name = llvm::get_value_name(outer_fn);
309-
let outer_fn_name = std::str::from_utf8(name).unwrap();
310-
ad_name.push_str(outer_fn_name);
307+
// functions.
308+
let outer_fn_name = llvm::get_value_name(outer_fn);
309+
ad_name.extend_from_slice(outer_fn_name);
311310

312311
// Let us assume the user wrote the following function square:
313312
//
@@ -400,7 +399,7 @@ fn generate_enzyme_call<'ll>(
400399
has_sret,
401400
);
402401

403-
let call = builder.call(enzyme_ty, ad_fn, &args, None);
402+
let call = builder.simple_call(enzyme_ty, ad_fn, &args, None);
404403

405404
// This part is a bit iffy. LLVM requires that a call to an inlineable function has some
406405
// metadata attached to it, but we just created this code oota. Given that the

compiler/rustc_codegen_llvm/src/declare.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use tracing::debug;
2424

2525
use crate::abi::FnAbiLlvmExt;
2626
use crate::common::AsCCharPtr;
27-
use crate::context::{CodegenCx, GenericCx, SCx, SimpleCx};
27+
use crate::context::{CodegenCx, GenericCx, SCx};
2828
use crate::llvm::AttributePlace::Function;
2929
use crate::llvm::Visibility;
3030
use crate::type_::Type;
@@ -35,17 +35,17 @@ use crate::{attributes, llvm};
3535
///
3636
/// If there’s a value with the same name already declared, the function will
3737
/// update the declaration and return existing Value instead.
38-
pub(crate) fn declare_simple_fn<'ll>(
39-
cx: &SimpleCx<'ll>,
40-
name: &str,
38+
pub(crate) fn declare_simple_fn<'ll, CX: Borrow<SCx<'ll>>>(
39+
cx: &GenericCx<'ll, CX>,
40+
name: &[u8],
4141
callconv: llvm::CallConv,
4242
unnamed: llvm::UnnamedAddr,
4343
visibility: llvm::Visibility,
4444
ty: &'ll Type,
4545
) -> &'ll Value {
4646
debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty);
4747
let llfn = unsafe {
48-
llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty)
48+
llvm::LLVMRustGetOrInsertFunction(cx.llmod(), name.as_c_char_ptr(), name.len(), ty)
4949
};
5050

5151
llvm::SetFunctionCallConv(llfn, callconv);
@@ -68,7 +68,7 @@ pub(crate) fn declare_raw_fn<'ll, 'tcx>(
6868
ty: &'ll Type,
6969
) -> &'ll Value {
7070
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
71-
let llfn = declare_simple_fn(cx, name, callconv, unnamed, visibility, ty);
71+
let llfn = declare_simple_fn(cx, name.as_bytes(), callconv, unnamed, visibility, ty);
7272

7373
let mut attrs = SmallVec::<[_; 4]>::new();
7474

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,14 +1753,6 @@ unsafe extern "C" {
17531753
) -> *mut OperandBundle<'_>;
17541754
pub(crate) fn LLVMDisposeOperandBundle(Bundle: ptr::NonNull<OperandBundle<'_>>);
17551755

1756-
pub(crate) fn LLVMBuildCall2<'a>(
1757-
B: &Builder<'a>,
1758-
Ty: &'a Type,
1759-
Fn: &'a Value,
1760-
Args: *const &'a Value,
1761-
NumArgs: c_uint,
1762-
Name: *const c_char,
1763-
) -> &'a Value;
17641756
pub(crate) fn LLVMBuildCallWithOperandBundles<'a>(
17651757
B: &Builder<'a>,
17661758
Ty: &'a Type,

compiler/rustc_codegen_llvm/src/llvm/mod.rs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ impl Intrinsic {
356356
self,
357357
llmod: &'ll Module,
358358
type_params: &[&'ll Type],
359-
) -> CSlice<u8> {
359+
) -> Vec<u8> {
360360
let mut len = 0;
361361
let ptr = unsafe {
362362
LLVMIntrinsicCopyOverloadedName2(
@@ -367,39 +367,15 @@ impl Intrinsic {
367367
&mut len,
368368
)
369369
};
370-
unsafe { CSlice::from_raw(ptr.cast(), len) }
371-
}
372-
}
373-
374-
pub(crate) struct CSlice<T: Copy> {
375-
ptr: *mut T,
376-
len: usize,
377-
}
378370

379-
impl<T: Copy> CSlice<T> {
380-
pub(crate) unsafe fn from_raw(ptr: *mut T, len: usize) -> Self {
381-
assert!(std::mem::size_of::<T>() != 0, "ZSTs aren't supported yet");
382-
Self { ptr, len }
383-
}
384-
}
371+
let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), len) };
372+
let copied = slice.to_vec();
385373

386-
impl<T: Copy> std::ops::Deref for CSlice<T> {
387-
type Target = [T];
388-
389-
fn deref(&self) -> &Self::Target {
390-
unsafe { slice::from_raw_parts(self.ptr, self.len) }
391-
}
392-
}
393-
394-
impl<T: Copy> std::ops::DerefMut for CSlice<T> {
395-
fn deref_mut(&mut self) -> &mut Self::Target {
396-
unsafe { slice::from_raw_parts_mut(self.ptr, self.len) }
397-
}
398-
}
374+
unsafe {
375+
libc::free(ptr.cast());
376+
}
399377

400-
impl<T: Copy> Drop for CSlice<T> {
401-
fn drop(&mut self) {
402-
unsafe { libc::free(self.ptr.cast()) }
378+
copied
403379
}
404380
}
405381

0 commit comments

Comments
 (0)