Skip to content

Commit 6d4eb0e

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 915af4f commit 6d4eb0e

File tree

7 files changed

+86
-22
lines changed

7 files changed

+86
-22
lines changed

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
314314
self.block.get_function()
315315
}
316316

317-
fn function_call(
317+
pub fn function_call(
318318
&mut self,
319319
func: Function<'gcc>,
320320
args: &[RValue<'gcc>],

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(),
@@ -397,9 +400,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
397400
fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
398401
let func_name = self.tcx.symbol_name(instance).name;
399402

400-
let func = if self.intrinsics.borrow().contains_key(func_name) {
401-
self.intrinsics.borrow()[func_name]
402-
} else if let Some(variable) = self.get_declared_value(func_name) {
403+
let func = if let Some(variable) = self.get_declared_value(func_name) {
403404
return variable;
404405
} else {
405406
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(
@@ -162,19 +161,6 @@ fn declare_raw_fn<'gcc>(
162161
param_types: &[Type<'gcc>],
163162
variadic: bool,
164163
) -> Function<'gcc> {
165-
if name.starts_with("llvm.") {
166-
let intrinsic = match name {
167-
"llvm.fma.f16" => {
168-
// fma is not a target builtin, but a normal builtin, so we handle it differently
169-
// here.
170-
cx.context.get_builtin_function("fma")
171-
}
172-
_ => llvm::intrinsic(name, cx),
173-
};
174-
175-
cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic);
176-
return intrinsic;
177-
}
178164
let func = if cx.functions.borrow().contains_key(name) {
179165
cx.functions.borrow()[name]
180166
} else {

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 41 additions & 1 deletion
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_ptr = self.get_fn_addr(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+
let fn_ptr = func.get_address(None);
650690
let fn_ty = fn_ptr.get_type();
651691

652692
let mut llargs = vec![];

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)