Skip to content

Commit 0563b07

Browse files
committed
Partially inline get_fn_addr/get_fn in codegen_llvm_intrinsic_call
This moves all LLVM intrinsic handling out of the regular call path for cg_gcc and makes it easier to hook into this code for future cg_llvm changes.
1 parent ba526ef commit 0563b07

File tree

6 files changed

+86
-22
lines changed

6 files changed

+86
-22
lines changed

compiler/rustc_codegen_gcc/src/context.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ pub struct CodegenCx<'gcc, 'tcx> {
9292
pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>,
9393
/// Cache function instances of monomorphic and polymorphic items
9494
pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
95+
/// Cache function instances of intrinsics
96+
pub intrinsic_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
9597
/// Cache generated vtables
9698
pub vtables:
9799
RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
@@ -280,6 +282,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
280282
linkage: Cell::new(FunctionType::Internal),
281283
instances: Default::default(),
282284
function_instances: Default::default(),
285+
intrinsic_instances: Default::default(),
283286
on_stack_params: Default::default(),
284287
on_stack_function_params: Default::default(),
285288
vtables: Default::default(),
@@ -399,9 +402,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
399402
fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
400403
let func_name = self.tcx.symbol_name(instance).name;
401404

402-
let func = if self.intrinsics.borrow().contains_key(func_name) {
403-
self.intrinsics.borrow()[func_name]
404-
} else if let Some(variable) = self.get_declared_value(func_name) {
405+
let func = if let Some(variable) = self.get_declared_value(func_name) {
405406
return variable;
406407
} else {
407408
get_fn(self, instance)

compiler/rustc_codegen_gcc/src/declare.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_target::callconv::FnAbi;
88

99
use crate::abi::{FnAbiGcc, FnAbiGccExt};
1010
use crate::context::CodegenCx;
11-
use crate::intrinsic::llvm;
1211

1312
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
1413
pub fn get_or_insert_global(
@@ -166,19 +165,6 @@ fn declare_raw_fn<'gcc>(
166165
param_types: &[Type<'gcc>],
167166
variadic: bool,
168167
) -> Function<'gcc> {
169-
if name.starts_with("llvm.") {
170-
let intrinsic = match name {
171-
"llvm.fma.f16" => {
172-
// fma is not a target builtin, but a normal builtin, so we handle it differently
173-
// here.
174-
cx.context.get_builtin_function("fma")
175-
}
176-
_ => llvm::intrinsic(name, cx),
177-
};
178-
179-
cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic);
180-
return intrinsic;
181-
}
182168
let func = if cx.functions.borrow().contains_key(name) {
183169
cx.functions.borrow()[name]
184170
} else {

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,47 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
646646
args: &[OperandRef<'tcx, Self::Value>],
647647
is_cleanup: bool,
648648
) -> Self::Value {
649-
let fn_val = self.get_fn(instance);
649+
let func = if let Some(&func) = self.intrinsic_instances.borrow().get(&instance) {
650+
func
651+
} else {
652+
let sym = self.tcx.symbol_name(instance).name;
653+
654+
let func = if let Some(func) = self.intrinsics.borrow().get(sym) {
655+
*func
656+
} else {
657+
self.linkage.set(FunctionType::Extern);
658+
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
659+
let fn_ty = fn_abi.gcc_type(self);
660+
661+
let func = match sym {
662+
"llvm.fma.f16" => {
663+
// fma is not a target builtin, but a normal builtin, so we handle it differently
664+
// here.
665+
self.context.get_builtin_function("fma")
666+
}
667+
_ => llvm::intrinsic(sym, self),
668+
};
669+
670+
self.intrinsics.borrow_mut().insert(sym.to_string(), func);
671+
672+
self.on_stack_function_params
673+
.borrow_mut()
674+
.insert(func, fn_ty.on_stack_param_indices);
675+
#[cfg(feature = "master")]
676+
for fn_attr in fn_ty.fn_attributes {
677+
func.add_attribute(fn_attr);
678+
}
679+
680+
crate::attributes::from_fn_attrs(self, func, instance);
681+
682+
func
683+
};
684+
685+
self.intrinsic_instances.borrow_mut().insert(instance, func);
686+
687+
func
688+
};
689+
*self.current_func.borrow_mut() = Some(func);
650690

651691
let mut llargs = vec![];
652692

@@ -679,7 +719,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
679719
}
680720

681721
// FIXME directly use the llvm intrinsic adjustment functions here
682-
let llret = self.function_call(fn_val, &llargs, None);
722+
let llret = self.function_call(func, &llargs, None);
683723
if is_cleanup {
684724
self.apply_attrs_to_cleanup_callsite(llret);
685725
}

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ pub(crate) struct FullCx<'ll, 'tcx> {
100100

101101
/// Cache instances of monomorphic and polymorphic items
102102
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
103+
/// Cache instances of intrinsics
104+
pub intrinsic_instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
103105
/// Cache generated vtables
104106
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>,
105107
/// Cache of constant strings,
@@ -620,6 +622,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
620622
tls_model,
621623
codegen_unit,
622624
instances: Default::default(),
625+
intrinsic_instances: Default::default(),
623626
vtables: Default::default(),
624627
const_str_cache: Default::default(),
625628
const_globals: Default::default(),

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::abi::FnAbiLlvmExt;
2828
use crate::builder::Builder;
2929
use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call};
3030
use crate::context::CodegenCx;
31+
use crate::declare::declare_raw_fn;
3132
use crate::errors::AutoDiffWithoutEnable;
3233
use crate::llvm::{self, Metadata, Type, Value};
3334
use crate::type_of::LayoutLlvmExt;
@@ -627,11 +628,41 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
627628
args: &[OperandRef<'tcx, Self::Value>],
628629
is_cleanup: bool,
629630
) -> Self::Value {
630-
let fn_ptr = self.get_fn_addr(instance);
631+
let tcx = self.tcx();
632+
631633
// FIXME remove usage of fn_abi
632634
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
633635
assert!(!fn_abi.ret.is_indirect());
634-
let fn_ty = self.fn_decl_backend_type(fn_abi);
636+
let fn_ty = fn_abi.llvm_type(self);
637+
638+
let fn_ptr = if let Some(&llfn) = self.intrinsic_instances.borrow().get(&instance) {
639+
llfn
640+
} else {
641+
let sym = tcx.symbol_name(instance).name;
642+
643+
// FIXME use get_intrinsic
644+
let llfn = if let Some(llfn) = self.get_declared_value(sym) {
645+
llfn
646+
} else {
647+
// Function addresses in Rust are never significant, allowing functions to
648+
// be merged.
649+
let llfn = declare_raw_fn(
650+
self,
651+
sym,
652+
fn_abi.llvm_cconv(self),
653+
llvm::UnnamedAddr::Global,
654+
llvm::Visibility::Default,
655+
fn_ty,
656+
);
657+
fn_abi.apply_attrs_llfn(self, llfn, Some(instance));
658+
659+
llfn
660+
};
661+
662+
self.intrinsic_instances.borrow_mut().insert(instance, llfn);
663+
664+
llfn
665+
};
635666

636667
let mut llargs = vec![];
637668

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER;
99
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
1010
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
1111
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
12-
use rustc_middle::ty::{self, Instance, Ty};
12+
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
1313
use rustc_middle::{bug, span_bug};
1414
use rustc_session::config::OptLevel;
1515
use rustc_span::Span;
@@ -1038,6 +1038,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10381038
&& let Some(name) = bx.tcx().codegen_fn_attrs(instance.def_id()).symbol_name
10391039
&& name.as_str().starts_with("llvm.")
10401040
{
1041+
assert!(!instance.args.has_infer());
1042+
assert!(!instance.args.has_escaping_bound_vars());
1043+
10411044
let dest_ty = destination.ty(&self.mir.local_decls, bx.tcx()).ty;
10421045
let return_dest = if dest_ty.is_unit() {
10431046
ReturnDest::Nothing

0 commit comments

Comments
 (0)