Skip to content

Commit c10176e

Browse files
trans: Only translate #[inline] functions if they are used somewhere.
1 parent 97b561a commit c10176e

File tree

4 files changed

+25
-87
lines changed

4 files changed

+25
-87
lines changed

src/librustc_trans/base.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1591,7 +1591,11 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
15911591
node: hir::ImplItemKind::Method(..), .. }) => {
15921592
let def_id = tcx.map.local_def_id(id);
15931593
let generics = tcx.lookup_generics(def_id);
1594-
generics.parent_types == 0 && generics.types.is_empty()
1594+
let attributes = tcx.get_attrs(def_id);
1595+
(generics.parent_types == 0 && generics.types.is_empty()) &&
1596+
// Functions marked with #[inline] are only ever translated
1597+
// with "internal" linkage and are never exported.
1598+
!attr::requests_inline(&attributes[..])
15951599
}
15961600

15971601
_ => false

src/librustc_trans/collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
401401
callees: &[TransItem<'tcx>],
402402
inlining_map: &mut InliningMap<'tcx>) {
403403
let is_inlining_candidate = |trans_item: &TransItem<'tcx>| {
404-
trans_item.is_from_extern_crate() || trans_item.requests_inline(tcx)
404+
trans_item.needs_local_copy(tcx)
405405
};
406406

407407
let inlining_candidates = callees.into_iter()

src/librustc_trans/partitioning.rs

Lines changed: 1 addition & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,6 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
261261
{
262262
let tcx = scx.tcx();
263263

264-
if let PartitioningStrategy::FixedUnitCount(1) = strategy {
265-
// If there is only a single codegen-unit, we can use a very simple
266-
// scheme and don't have to bother with doing much analysis.
267-
return vec![single_codegen_unit(tcx, trans_items, reachable)];
268-
}
269-
270264
// In the first step, we place all regular translation items into their
271265
// respective 'home' codegen unit. Regular translation items are all
272266
// functions and statics defined in the local crate.
@@ -320,7 +314,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
320314
let mut codegen_units = FnvHashMap();
321315

322316
for trans_item in trans_items {
323-
let is_root = !trans_item.is_instantiated_only_on_demand();
317+
let is_root = !trans_item.is_instantiated_only_on_demand(tcx);
324318

325319
if is_root {
326320
let characteristic_def_id = characteristic_def_id_of_trans_item(scx, trans_item);
@@ -454,7 +448,6 @@ fn place_inlined_translation_items<'tcx>(initial_partitioning: PreInliningPartit
454448
// reliably in that case.
455449
new_codegen_unit.items.insert(trans_item, llvm::InternalLinkage);
456450
} else {
457-
assert!(trans_item.is_instantiated_only_on_demand());
458451
// We can't be sure if this will also be instantiated
459452
// somewhere else, so we add an instance here with
460453
// InternalLinkage so we don't get any conflicts.
@@ -550,68 +543,6 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
550543
return token::intern_and_get_ident(&mod_path[..]);
551544
}
552545

553-
fn single_codegen_unit<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
554-
trans_items: I,
555-
reachable: &NodeSet)
556-
-> CodegenUnit<'tcx>
557-
where I: Iterator<Item = TransItem<'tcx>>
558-
{
559-
let mut items = FnvHashMap();
560-
561-
for trans_item in trans_items {
562-
let linkage = trans_item.explicit_linkage(tcx).unwrap_or_else(|| {
563-
match trans_item {
564-
TransItem::Static(node_id) => {
565-
if reachable.contains(&node_id) {
566-
llvm::ExternalLinkage
567-
} else {
568-
llvm::PrivateLinkage
569-
}
570-
}
571-
TransItem::DropGlue(_) => {
572-
llvm::InternalLinkage
573-
}
574-
TransItem::Fn(instance) => {
575-
if trans_item.is_generic_fn() {
576-
// FIXME(mw): Assigning internal linkage to all
577-
// monomorphizations is potentially a waste of space
578-
// since monomorphizations could be shared between
579-
// crates. The main reason for making them internal is
580-
// a limitation in MingW's binutils that cannot deal
581-
// with COFF object that have more than 2^15 sections,
582-
// which is something that can happen for large programs
583-
// when every function gets put into its own COMDAT
584-
// section.
585-
llvm::InternalLinkage
586-
} else if trans_item.is_from_extern_crate() {
587-
// FIXME(mw): It would be nice if we could mark these as
588-
// `AvailableExternallyLinkage`, since they should have
589-
// been instantiated in the extern crate. But this
590-
// sometimes leads to crashes on Windows because LLVM
591-
// does not handle exception handling table instantiation
592-
// reliably in that case.
593-
llvm::InternalLinkage
594-
} else if reachable.contains(&tcx.map
595-
.as_local_node_id(instance.def)
596-
.unwrap()) {
597-
llvm::ExternalLinkage
598-
} else {
599-
// Functions that are not visible outside this crate can
600-
// be marked as internal.
601-
llvm::InternalLinkage
602-
}
603-
}
604-
}
605-
});
606-
607-
items.insert(trans_item, linkage);
608-
}
609-
610-
CodegenUnit::new(
611-
numbered_codegen_unit_name(&tcx.crate_name[..], 0),
612-
items)
613-
}
614-
615546
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
616547
token::intern_and_get_ident(&format!("{}{}{}",
617548
crate_name,

src/librustc_trans/trans_item.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,6 @@ impl<'a, 'tcx> TransItem<'tcx> {
241241
}
242242
}
243243

244-
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
245-
match *self {
246-
TransItem::Fn(ref instance) => {
247-
instance.substs.types().next().is_some() || {
248-
let attributes = tcx.get_attrs(instance.def);
249-
attr::requests_inline(&attributes[..])
250-
}
251-
}
252-
TransItem::DropGlue(..) => true,
253-
TransItem::Static(..) => false,
254-
}
255-
}
256-
257244
pub fn is_from_extern_crate(&self) -> bool {
258245
match *self {
259246
TransItem::Fn(ref instance) => !instance.def.is_local(),
@@ -262,10 +249,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
262249
}
263250
}
264251

265-
pub fn is_instantiated_only_on_demand(&self) -> bool {
252+
/// True if the translation item should only be translated to LLVM IR if
253+
/// it is referenced somewhere (like inline functions, for example).
254+
pub fn is_instantiated_only_on_demand(&self, tcx: TyCtxt) -> bool {
266255
match *self {
267256
TransItem::Fn(ref instance) => {
268-
!instance.def.is_local() || instance.substs.types().next().is_some()
257+
!instance.def.is_local() ||
258+
instance.substs.types().next().is_some() ||
259+
attr::requests_inline(&tcx.get_attrs(instance.def)[..])
269260
}
270261
TransItem::DropGlue(..) => true,
271262
TransItem::Static(..) => false,
@@ -282,6 +273,18 @@ impl<'a, 'tcx> TransItem<'tcx> {
282273
}
283274
}
284275

276+
/// Returns true if there has to be a local copy of this TransItem in every
277+
/// codegen unit that references it (as with inlined functions, for example)
278+
pub fn needs_local_copy(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
279+
// Currently everything that is instantiated only on demand is done so
280+
// with "internal" linkage, so we need a copy to be present in every
281+
// codegen unit.
282+
// This is coincidental: We could also instantiate something only if it
283+
// is referenced (e.g. a regular, private function) but place it in its
284+
// own codegen unit with "external" linkage.
285+
self.is_instantiated_only_on_demand(tcx)
286+
}
287+
285288
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
286289
let def_id = match *self {
287290
TransItem::Fn(ref instance) => instance.def,

0 commit comments

Comments
 (0)