Auto merge of #121421 - saethlin:smarter-mono, r= · rust-lang/rust@b183b7a (original) (raw)

`@@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};

`

10

10

`use crate::ty::print::{FmtPrinter, Printer};

`

11

11

`use crate::ty::visit::TypeVisitableExt;

`

12

12

`use crate::ty::{self, List, Ty, TyCtxt};

`

13

``

`-

use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex};

`

``

13

`+

use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex};

`

14

14

`use crate::ty::{GenericArg, GenericArgsRef};

`

15

15

``

16

16

`use rustc_data_structures::captures::Captures;

`

`@@ -29,6 +29,7 @@ pub use rustc_ast::Mutability;

`

29

29

`use rustc_data_structures::fx::FxHashMap;

`

30

30

`use rustc_data_structures::fx::FxHashSet;

`

31

31

`use rustc_data_structures::graph::dominators::Dominators;

`

``

32

`+

use rustc_index::bit_set::BitSet;

`

32

33

`use rustc_index::{Idx, IndexSlice, IndexVec};

`

33

34

`use rustc_serialize::{Decodable, Encodable};

`

34

35

`use rustc_span::symbol::Symbol;

`

`@@ -642,6 +643,73 @@ impl<'tcx> Body<'tcx> {

`

642

643

`self.injection_phase.is_some()

`

643

644

`}

`

644

645

``

``

646

`+

/// Finds which basic blocks are actually reachable for a specific

`

``

647

`+

/// monomorphization of this body.

`

``

648

`+

///

`

``

649

`+

/// This is allowed to have false positives; just because this says a block

`

``

650

`+

/// is reachable doesn't mean that's necessarily true. It's thus always

`

``

651

`+

/// legal for this to return a filled set.

`

``

652

`+

///

`

``

653

`` +

/// Regardless, the [BitSet::domain_size] of the returned set will always

``

``

654

`` +

/// exactly match the number of blocks in the body so that contains

``

``

655

`+

/// checks can be done without worrying about panicking.

`

``

656

`+

///

`

``

657

`` +

/// The main case this supports is filtering out if <T as Trait>::CONST

``

``

658

`+

/// bodies that can't be removed in generic MIR, but can be removed once

`

``

659

`` +

/// the specific T is known.

``

``

660

`+

///

`

``

661

`+

/// This is used in the monomorphization collector as well as in codegen.

`

``

662

`+

pub fn reachable_blocks_in_mono(

`

``

663

`+

&self,

`

``

664

`+

tcx: TyCtxt<'tcx>,

`

``

665

`+

instance: Instance<'tcx>,

`

``

666

`+

) -> BitSet {

`

``

667

`+

if instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_none() {

`

``

668

`+

// If it's non-generic, then mir-opt const prop has already run, meaning it's

`

``

669

`+

// probably not worth doing any further filtering. So call everything reachable.

`

``

670

`+

return BitSet::new_filled(self.basic_blocks.len());

`

``

671

`+

}

`

``

672

+

``

673

`+

let mut set = BitSet::new_empty(self.basic_blocks.len());

`

``

674

`+

self.reachable_blocks_in_mono_from(tcx, instance, &mut set, START_BLOCK);

`

``

675

`+

set

`

``

676

`+

}

`

``

677

+

``

678

`+

fn reachable_blocks_in_mono_from(

`

``

679

`+

&self,

`

``

680

`+

tcx: TyCtxt<'tcx>,

`

``

681

`+

instance: Instance<'tcx>,

`

``

682

`+

set: &mut BitSet,

`

``

683

`+

bb: BasicBlock,

`

``

684

`+

) {

`

``

685

`+

if !set.insert(bb) {

`

``

686

`+

return;

`

``

687

`+

}

`

``

688

+

``

689

`+

let data = &self.basic_blocks[bb];

`

``

690

+

``

691

`+

if let TerminatorKind::SwitchInt { discr: Operand::Constant(constant), targets } =

`

``

692

`+

&data.terminator().kind

`

``

693

`+

{

`

``

694

`+

let env = ty::ParamEnv::reveal_all();

`

``

695

`+

let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions(

`

``

696

`+

tcx,

`

``

697

`+

env,

`

``

698

`+

crate::ty::EarlyBinder::bind(constant.const_),

`

``

699

`+

);

`

``

700

`+

if let Some(bits) = mono_literal.try_eval_bits(tcx, env) {

`

``

701

`+

let target = targets.target_for_value(bits);

`

``

702

`+

return self.reachable_blocks_in_mono_from(tcx, instance, set, target);

`

``

703

`+

} else {

`

``

704

`+

bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance);

`

``

705

`+

}

`

``

706

`+

}

`

``

707

+

``

708

`+

for target in data.terminator().successors() {

`

``

709

`+

self.reachable_blocks_in_mono_from(tcx, instance, set, target);

`

``

710

`+

}

`

``

711

`+

}

`

``

712

+

645

713

`` /// For a Location in this scope, determine what the "caller location" at that point is. This

``

646

714

`` /// is interesting because of inlining: the #[track_caller] attribute of inlined functions

``

647

715

`` /// must be honored. Falls back to the tracked_caller value for #[track_caller] functions,

``