Disable non-required MIR opts with optimize(none)
Co-authored-by: Waffle Lapkin <waffle.lapkin@gmail.com>
This commit is contained in:
parent
cd848c9f3e
commit
7a9661d768
57 changed files with 319 additions and 10 deletions
|
@ -46,6 +46,12 @@ pub enum OptimizeAttr {
|
|||
Size,
|
||||
}
|
||||
|
||||
impl OptimizeAttr {
|
||||
pub fn do_not_optimize(&self) -> bool {
|
||||
matches!(self, Self::DoNotOptimize)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub enum DiagnosticAttribute {
|
||||
// tidy-alphabetical-start
|
||||
|
|
|
@ -116,4 +116,8 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
|
|||
// We may have invalidated some `cleanup` blocks so clean those up now.
|
||||
super::simplify::remove_dead_blocks(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,4 +75,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards {
|
|||
|
||||
body.basic_blocks_mut().extend(new_blocks);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
|
|||
|
||||
patch.apply(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn add_move_for_packed_drop<'tcx>(
|
||||
|
|
|
@ -176,4 +176,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,8 @@ impl<'tcx> crate::MirPass<'tcx> for Subtyper {
|
|||
}
|
||||
checker.patcher.apply(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,10 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct PointerFinder<'a, 'tcx> {
|
||||
|
|
|
@ -72,4 +72,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
|
|||
decl.user_ty = None;
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,10 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
|
|||
crate::simplify::remove_unused_definitions(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// `SsaLocals` computed equivalence classes between locals considering copy/move assignments.
|
||||
|
|
|
@ -1688,6 +1688,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
|
|||
// Run derefer to fix Derefs that are not in the first place
|
||||
deref_finder(tcx, body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields
|
||||
|
|
|
@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage {
|
|||
|
||||
instrument_function_for_coverage(tcx, mir_body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) {
|
||||
|
|
|
@ -69,7 +69,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
// Don't do any inference if codegen optimizations are disabled and also MIR inlining is not
|
||||
// enabled. This ensures that we do inference even if someone only passes -Zinline-mir,
|
||||
// which is less confusing than having to also enable -Copt-level=1.
|
||||
let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline)
|
||||
let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
|
||||
|| inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id());
|
||||
if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run {
|
||||
return false;
|
||||
|
|
|
@ -36,6 +36,10 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn has_back_edge(
|
||||
|
|
|
@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
|
|||
let mut patch = visitor.patch;
|
||||
debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body));
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Currently, places that have their reference taken cannot be tracked. Although this would
|
||||
|
|
|
@ -147,4 +147,8 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination {
|
|||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
eliminate(tcx, body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
|
|||
simplify_cfg(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct OptApplier<'tcx> {
|
||||
|
|
|
@ -81,4 +81,8 @@ impl<'tcx> crate::MirPass<'tcx> for Derefer {
|
|||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
deref_finder(tcx, body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -240,6 +240,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
|
|||
|
||||
trace!(round_count);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
|
|
@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for Marker {
|
|||
}
|
||||
|
||||
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
|
||||
|
|
|
@ -227,6 +227,10 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
|||
simplify_cfg(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -150,4 +150,8 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,10 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
|
|||
elaborate_patch.apply(body);
|
||||
deref_finder(tcx, body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Records unwind edges which are known to be unreachable, because they are in `drop` terminators
|
||||
|
|
|
@ -163,6 +163,10 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
|
|||
// statements.
|
||||
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
newtype_index! {
|
||||
|
|
|
@ -53,4 +53,8 @@ impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
|
|||
body.local_decls.raw.truncate(body.arg_count + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,10 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
|
|||
deref_finder(tcx, body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ForceInline;
|
||||
|
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline {
|
|||
false
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let span = trace_span!("force_inline", body = %tcx.def_path_str(body.source.def_id()));
|
||||
let _guard = span.enter();
|
||||
|
|
|
@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
|
|||
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct InstSimplifyContext<'a, 'tcx> {
|
||||
|
|
|
@ -105,6 +105,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
|||
}
|
||||
OpportunitySet::new(body, opportunities).apply(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -200,6 +200,10 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl EnumSizeOpt {
|
||||
|
|
|
@ -388,6 +388,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
|
|||
&Lint(sanity_check::SanityCheck),
|
||||
],
|
||||
None,
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
tcx.alloc_steal_mir(body)
|
||||
}
|
||||
|
@ -440,6 +441,7 @@ fn mir_promoted(
|
|||
&mut body,
|
||||
&[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
|
||||
Some(MirPhase::Analysis(AnalysisPhase::Initial)),
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
|
||||
lint_tail_expr_drop_order::run_lint(tcx, def, &body);
|
||||
|
@ -473,7 +475,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
|
|||
};
|
||||
|
||||
let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const);
|
||||
pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None);
|
||||
pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed);
|
||||
|
||||
body
|
||||
}
|
||||
|
@ -493,7 +495,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
|
|||
let is_fn_like = tcx.def_kind(def).is_fn_like();
|
||||
if is_fn_like {
|
||||
// Do not compute the mir call graph without said call graph actually being used.
|
||||
if pm::should_run_pass(tcx, &inline::Inline)
|
||||
if pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
|
||||
|| inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id())
|
||||
{
|
||||
tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
|
||||
|
@ -533,6 +535,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
|
|||
&Lint(post_drop_elaboration::CheckLiveDrops),
|
||||
],
|
||||
None,
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -557,7 +560,13 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
&deref_separator::Derefer,
|
||||
];
|
||||
|
||||
pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)));
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
body,
|
||||
passes,
|
||||
Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)),
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the sequence of passes that lowers analysis to runtime MIR.
|
||||
|
@ -597,7 +606,13 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
&simplify::SimplifyCfg::PreOptimizations,
|
||||
];
|
||||
|
||||
pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
body,
|
||||
passes,
|
||||
Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
|
||||
// Clear this by anticipation. Optimizations and runtime MIR have no reason to look
|
||||
// into this information, which is meant for borrowck diagnostics.
|
||||
|
@ -611,6 +626,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
WithMinOptLevel(1, x)
|
||||
}
|
||||
|
||||
let def_id = body.source.def_id();
|
||||
let optimizations = if tcx.def_kind(def_id).has_codegen_attrs()
|
||||
&& tcx.codegen_fn_attrs(def_id).optimize.do_not_optimize()
|
||||
{
|
||||
pm::Optimizations::Suppressed
|
||||
} else {
|
||||
pm::Optimizations::Allowed
|
||||
};
|
||||
|
||||
// The main optimizations that we do on MIR.
|
||||
pm::run_passes(
|
||||
tcx,
|
||||
|
@ -683,6 +707,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
|||
&dump_mir::Marker("PreCodegen"),
|
||||
],
|
||||
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
|
||||
optimizations,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -325,4 +325,8 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
|
|||
lower_slice_len_call(block, slice_len_fn_item_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_item_def_id: DefId) {
|
||||
|
|
|
@ -49,6 +49,10 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
|
|||
simplify_cfg(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
trait SimplifyMatch<'tcx> {
|
||||
|
|
|
@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
|
|||
visitor.visit_body(body);
|
||||
body.set_mentioned_items(visitor.mentioned_items);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are
|
||||
|
|
|
@ -36,4 +36,8 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
|
|||
|
||||
simplify::remove_dead_blocks(body)
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
|
|||
// The return place is always mutable.
|
||||
ret_decl.mutability = Mutability::Mut;
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// MIR that is eligible for the NRVO must fulfill two conditions:
|
||||
|
|
|
@ -90,6 +90,11 @@ pub(super) trait MirPass<'tcx> {
|
|||
fn is_mir_dump_enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns `true` if this pass must be run (i.e. it is required for soundness).
|
||||
/// For passes which are strictly optimizations, this should return `false`.
|
||||
/// If this is `false`, `#[optimize(none)]` will disable the pass.
|
||||
fn is_required(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is
|
||||
|
@ -134,6 +139,10 @@ where
|
|||
fn is_mir_dump_enabled(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct WithMinOptLevel<T>(pub u32, pub T);
|
||||
|
@ -153,6 +162,19 @@ where
|
|||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
self.1.run_pass(tcx, body)
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
self.1.is_required()
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to allow non-[required] optimizations
|
||||
///
|
||||
/// [required]: MirPass::is_required
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum Optimizations {
|
||||
Suppressed,
|
||||
Allowed,
|
||||
}
|
||||
|
||||
/// Run the sequence of passes without validating the MIR after each pass. The MIR is still
|
||||
|
@ -163,7 +185,7 @@ pub(super) fn run_passes_no_validate<'tcx>(
|
|||
passes: &[&dyn MirPass<'tcx>],
|
||||
phase_change: Option<MirPhase>,
|
||||
) {
|
||||
run_passes_inner(tcx, body, passes, phase_change, false);
|
||||
run_passes_inner(tcx, body, passes, phase_change, false, Optimizations::Allowed);
|
||||
}
|
||||
|
||||
/// The optional `phase_change` is applied after executing all the passes, if present
|
||||
|
@ -172,11 +194,16 @@ pub(super) fn run_passes<'tcx>(
|
|||
body: &mut Body<'tcx>,
|
||||
passes: &[&dyn MirPass<'tcx>],
|
||||
phase_change: Option<MirPhase>,
|
||||
optimizations: Optimizations,
|
||||
) {
|
||||
run_passes_inner(tcx, body, passes, phase_change, true);
|
||||
run_passes_inner(tcx, body, passes, phase_change, true, optimizations);
|
||||
}
|
||||
|
||||
pub(super) fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool
|
||||
pub(super) fn should_run_pass<'tcx, P>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pass: &P,
|
||||
optimizations: Optimizations,
|
||||
) -> bool
|
||||
where
|
||||
P: MirPass<'tcx> + ?Sized,
|
||||
{
|
||||
|
@ -196,7 +223,8 @@ where
|
|||
);
|
||||
*polarity
|
||||
});
|
||||
overridden.unwrap_or_else(|| pass.is_enabled(tcx.sess))
|
||||
let suppressed = !pass.is_required() && matches!(optimizations, Optimizations::Suppressed);
|
||||
overridden.unwrap_or_else(|| !suppressed && pass.is_enabled(tcx.sess))
|
||||
}
|
||||
|
||||
fn run_passes_inner<'tcx>(
|
||||
|
@ -205,6 +233,7 @@ fn run_passes_inner<'tcx>(
|
|||
passes: &[&dyn MirPass<'tcx>],
|
||||
phase_change: Option<MirPhase>,
|
||||
validate_each: bool,
|
||||
optimizations: Optimizations,
|
||||
) {
|
||||
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||
trace!(?overridden_passes);
|
||||
|
@ -243,7 +272,7 @@ fn run_passes_inner<'tcx>(
|
|||
for pass in passes {
|
||||
let name = pass.name();
|
||||
|
||||
if !should_run_pass(tcx, *pass) {
|
||||
if !should_run_pass(tcx, *pass, optimizations) {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize {
|
|||
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
|
||||
PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct PostAnalysisNormalizeVisitor<'tcx> {
|
||||
|
|
|
@ -35,6 +35,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
|
|||
|
||||
permute(body.basic_blocks.as_mut(), &updater.map);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Rearranges the locals into *use* order.
|
||||
|
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
|
|||
|
||||
permute(&mut body.local_decls, &updater.map);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) {
|
||||
|
|
|
@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> {
|
|||
let promoted = promote_candidates(body, tcx, temps, promotable_candidates);
|
||||
self.promoted_fragments.set(promoted);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// State of a temporary during collection and promotion.
|
||||
|
|
|
@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
|
|||
debug!(def_id = ?body.source.def_id());
|
||||
while propagate_ssa(tcx, body) {}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
|
||||
|
|
|
@ -74,6 +74,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
|
|||
|
||||
debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl RemoveNoopLandingPads {
|
||||
|
|
|
@ -20,4 +20,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
|
|||
block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn is_needs_drop_and_init<'tcx>(
|
||||
|
|
|
@ -38,4 +38,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
|
|||
simplify_cfg(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
|
|||
replacer.visit_basic_block_data(bb, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct Replacer<'a, 'tcx> {
|
||||
|
|
|
@ -119,6 +119,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
|
|||
&add_call_guards::CriticalCallEdges,
|
||||
],
|
||||
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
|
||||
pm::Optimizations::Allowed,
|
||||
);
|
||||
|
||||
return body;
|
||||
|
|
|
@ -83,6 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
|
|||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
|
||||
simplify_cfg(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct CfgSimplifier<'a, 'tcx> {
|
||||
|
@ -405,6 +409,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
|
|||
body.local_decls.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
|
||||
|
|
|
@ -60,4 +60,8 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
|
|||
body.basic_blocks_mut()[idx].statements.insert(0, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct OptimizationFinder<'a, 'tcx> {
|
||||
|
|
|
@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
|
@ -48,6 +48,10 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Identify all locals that are not eligible for SROA.
|
||||
|
|
|
@ -31,4 +31,8 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
|
|||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,4 +208,8 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
|
|||
|
||||
patch.apply(body);
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,10 @@ impl crate::MirPass<'_> for UnreachablePropagation {
|
|||
body.basic_blocks_mut()[bb].statements.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Return whether the current terminator is fully unreachable.
|
||||
|
|
|
@ -91,6 +91,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_required(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct CfgChecker<'a, 'tcx> {
|
||||
|
|
32
tests/mir-opt/optimize_none.rs
Normal file
32
tests/mir-opt/optimize_none.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
//@ revisions: NO-OPT SPEED-OPT
|
||||
//@[NO-OPT] compile-flags: -Copt-level=0
|
||||
//@[SPEED-OPT] compile-flags: -Copt-level=3 -Coverflow-checks=y
|
||||
|
||||
#![feature(optimize_attribute)]
|
||||
|
||||
#[optimize(none)]
|
||||
pub fn add_noopt() -> i32 {
|
||||
// CHECK-LABEL: fn add_noopt(
|
||||
// CHECK: AddWithOverflow(const 1_i32, const 2_i32);
|
||||
// CHECK-NEXT: assert
|
||||
1 + 2
|
||||
}
|
||||
|
||||
#[optimize(none)]
|
||||
pub fn const_branch() -> i32 {
|
||||
// CHECK-LABEL: fn const_branch(
|
||||
// CHECK: switchInt(const true) -> [0: [[FALSE:bb[0-9]+]], otherwise: [[TRUE:bb[0-9]+]]];
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: [[FALSE]]: {
|
||||
// CHECK-NEXT: _0 = const 0
|
||||
// CHECK-NEXT: goto
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: [[TRUE]]: {
|
||||
// CHECK-NEXT: _0 = const 1
|
||||
// CHECK-NEXT: goto
|
||||
// CHECK-NEXT: }
|
||||
|
||||
if true { 1 } else { 0 }
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue