Skip to content

Commit 88c82b1

Browse files
committed
Skip post-mono opts when mono doesn't reveal new information
1 parent 7c9a410 commit 88c82b1

File tree

6 files changed

+75
-35
lines changed

6 files changed

+75
-35
lines changed

compiler/rustc_middle/src/mir/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@ pub struct Body<'tcx> {
375375
#[type_foldable(identity)]
376376
#[type_visitable(ignore)]
377377
pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>,
378+
379+
pub is_codegen_mir: bool,
378380
}
379381

380382
impl<'tcx> Body<'tcx> {
@@ -418,6 +420,7 @@ impl<'tcx> Body<'tcx> {
418420
tainted_by_errors,
419421
coverage_info_hi: None,
420422
function_coverage_info: None,
423+
is_codegen_mir: false,
421424
};
422425
body.is_polymorphic = body.has_non_region_param();
423426
body
@@ -449,6 +452,7 @@ impl<'tcx> Body<'tcx> {
449452
tainted_by_errors: None,
450453
coverage_info_hi: None,
451454
function_coverage_info: None,
455+
is_codegen_mir: false,
452456
};
453457
body.is_polymorphic = body.has_non_region_param();
454458
body

compiler/rustc_mir_build/src/builder/custom/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub(super) fn build_custom_mir<'tcx>(
6161
pass_count: 0,
6262
coverage_info_hi: None,
6363
function_coverage_info: None,
64+
is_codegen_mir: false,
6465
};
6566

6667
body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));

compiler/rustc_mir_transform/src/lib.rs

+65-25
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_middle::mir::{
3131
Location, MirPhase, NullOp, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue,
3232
START_BLOCK, SourceInfo, Statement, StatementKind, TerminatorKind,
3333
};
34-
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
34+
use rustc_middle::ty::{self, GenericParamDefKind, Instance, TyCtxt, TypeVisitableExt};
3535
use rustc_middle::util::Providers;
3636
use rustc_middle::{bug, query, span_bug};
3737
use rustc_mir_build::builder::build_mir;
@@ -794,26 +794,47 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
794794

795795
run_optimization_passes(tcx, &mut body);
796796

797-
let mut vis = MonoCompatVisitor { contains_ubcheck: false };
798-
vis.visit_body(&body);
797+
// If the body is polymorphic, we're done. Otherwise, we're going to turn the body into codegen
798+
// MIR ahead of time, as an optimization.
799+
if tcx.generics_of(did).requires_monomorphization(tcx) {
800+
return body;
801+
}
799802

800-
// If the MIR is already monomorphic, we can transform it to codegen MIR right away.
801-
if !tcx.generics_of(did).requires_monomorphization(tcx)
802-
&& !vis.contains_ubcheck
803-
&& !body.has_aliases()
804-
{
805-
let instance = Instance::mono(tcx, did.into());
806-
body = instance.instantiate_mir_and_normalize_erasing_regions(
807-
tcx,
808-
ty::TypingEnv::fully_monomorphized(),
809-
ty::EarlyBinder::bind(body),
810-
);
803+
// If the body has impossible predicates, the normalization we need to do to turn this into
804+
// post-mono MIR will fail. So we detect that case and return just optimized MIR.
805+
let args = ty::GenericArgs::for_item(tcx, did.into(), |param, _| match param.kind {
806+
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
807+
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
808+
unreachable!(
809+
"`requires_monomorphization` check means that we should have no type/const params"
810+
)
811+
}
812+
});
813+
if tcx.instantiate_and_check_impossible_predicates((did.to_def_id(), args)) {
814+
return body;
815+
}
811816

812-
// Monomoprhizing this body didn't reveal any new information that is useful for
813-
// optimizations, so we just run passes that make the MIR ready for codegen backends.
814-
pm::run_passes_no_validate(tcx, &mut body, &[&add_call_guards::CriticalCallEdges], None);
817+
// If the body contains the UB check intrinsic that is only to be monomorphized at codegen
818+
// time, we cannot generate codegen MIR early. We want post-mono optimizations to optimize on
819+
// whether UB checks are enabled or disabled at codegen time.
820+
let mut vis = MonoCompatVisitor { contains_ubcheck: false, contains_generic_const: false };
821+
vis.visit_body(&body);
822+
if vis.contains_ubcheck {
823+
return body;
815824
}
816825

826+
let instance = Instance::mono(tcx, did.to_def_id());
827+
body = instance.instantiate_mir_and_normalize_erasing_regions(
828+
tcx,
829+
ty::TypingEnv::fully_monomorphized(),
830+
ty::EarlyBinder::bind(body),
831+
);
832+
833+
// Monomoprhizing this body didn't reveal any new information that is useful for
834+
// optimizations, so we just run passes that make the MIR ready for codegen backends.
835+
pm::run_passes_no_validate(tcx, &mut body, &[&add_call_guards::CriticalCallEdges], None);
836+
body.is_codegen_mir = true;
837+
817838
body
818839
}
819840

@@ -822,6 +843,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
822843
// Currently, it looks for NullOp::UbChecks because that must be resolved at codegen.
823844
struct MonoCompatVisitor {
824845
contains_ubcheck: bool,
846+
contains_generic_const: bool,
825847
}
826848

827849
impl<'tcx> Visitor<'tcx> for MonoCompatVisitor {
@@ -831,25 +853,43 @@ impl<'tcx> Visitor<'tcx> for MonoCompatVisitor {
831853
}
832854
self.super_rvalue(rvalue, location);
833855
}
856+
857+
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
858+
if constant.has_non_region_param() {
859+
self.contains_generic_const = true;
860+
}
861+
self.super_const_operand(constant, location);
862+
}
834863
}
835864

836865
pub fn build_codegen_mir<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> &'tcx Body<'tcx> {
837866
let body = tcx.instance_mir(instance.def);
838867

839-
let mut vis = MonoCompatVisitor { contains_ubcheck: false };
840-
vis.visit_body(&body);
868+
// If we have generic params, assert that we didn't get codegen MIR out of instance_mir
869+
if instance.args.non_erasable_generics().next().is_some() {
870+
assert!(!body.is_codegen_mir);
871+
}
872+
873+
let body = if !body.is_codegen_mir {
874+
let mut vis = MonoCompatVisitor { contains_ubcheck: false, contains_generic_const: false };
875+
vis.visit_body(&body);
841876

842-
// MIR for monomorphic defs has already been fully optimized in optimized_mir.
843-
let body = if instance.args.non_erasable_generics().next().is_some()
844-
|| vis.contains_ubcheck
845-
|| body.has_aliases()
846-
{
847877
let mut body = instance.instantiate_mir_and_normalize_erasing_regions(
848878
tcx,
849879
ty::TypingEnv::fully_monomorphized(),
850880
ty::EarlyBinder::bind(body.clone()),
851881
);
852-
transform_to_codegen_mir(tcx, &mut body);
882+
if vis.contains_ubcheck || vis.contains_generic_const {
883+
transform_to_codegen_mir(tcx, &mut body);
884+
} else {
885+
pm::run_passes_no_validate(
886+
tcx,
887+
&mut body,
888+
&[&add_call_guards::CriticalCallEdges],
889+
None,
890+
);
891+
}
892+
body.is_codegen_mir = true;
853893
tcx.arena.alloc(body)
854894
} else {
855895
body

tests/ui/layout/layout-cycle.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ build-fail
2-
//~^ ERROR: cycle detected when computing layout of
2+
//~^ ERROR: a cycle occurred during layout computation
3+
//~| ERROR: cycle detected when computing layout of
34

45
// Issue #111176 -- ensure that we do not emit ICE on layout cycles
56

tests/ui/layout/layout-cycle.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@ error[E0391]: cycle detected when computing layout of `S<S<()>>`
22
|
33
= note: ...which requires computing layout of `<S<()> as Tr>::I`...
44
= note: ...which again requires computing layout of `S<S<()>>`, completing the cycle
5-
note: cycle used when finalizing codegen MIR for `core::mem::size_of::<S<S<()>>>`
6-
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
75
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
86

9-
note: the above error was encountered while instantiating `fn std::mem::size_of::<S<S<()>>>`
10-
--> $DIR/layout-cycle.rs:25:5
11-
|
12-
LL | mem::size_of::<S<T>>()
13-
| ^^^^^^^^^^^^^^^^^^^^^^
7+
error: failed to get layout for S<S<()>>: a cycle occurred during layout computation
148

15-
error: aborting due to 1 previous error
9+
error: aborting due to 2 previous errors
1610

1711
For more information about this error, try `rustc --explain E0391`.

tests/ui/recursion_limit/zero-overflow.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0275]: overflow evaluating the requirement `{closure@rt::lang_start<()>::{closure#0}}: Freeze`
1+
error[E0275]: overflow evaluating the requirement `&mut Self: DispatchFromDyn<&mut RustaceansAreAwesome>`
22
|
33
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`zero_overflow`)
44

0 commit comments

Comments
 (0)