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,
|
Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl OptimizeAttr {
|
||||||
|
pub fn do_not_optimize(&self) -> bool {
|
||||||
|
matches!(self, Self::DoNotOptimize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||||
pub enum DiagnosticAttribute {
|
pub enum DiagnosticAttribute {
|
||||||
// tidy-alphabetical-start
|
// 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.
|
// We may have invalidated some `cleanup` blocks so clean those up now.
|
||||||
super::simplify::remove_dead_blocks(body);
|
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);
|
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);
|
patch.apply(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_move_for_packed_drop<'tcx>(
|
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);
|
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> {
|
struct PointerFinder<'a, 'tcx> {
|
||||||
|
|
|
@ -72,4 +72,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
|
||||||
decl.user_ty = None;
|
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);
|
crate::simplify::remove_unused_definitions(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `SsaLocals` computed equivalence classes between locals considering copy/move assignments.
|
/// `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
|
// Run derefer to fix Derefs that are not in the first place
|
||||||
deref_finder(tcx, body);
|
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
|
/// 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);
|
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>) {
|
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
|
// 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,
|
// 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.
|
// 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());
|
|| inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id());
|
||||||
if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run {
|
if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -36,6 +36,10 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_back_edge(
|
fn has_back_edge(
|
||||||
|
|
|
@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
|
||||||
let mut patch = visitor.patch;
|
let mut patch = visitor.patch;
|
||||||
debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body));
|
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
|
// 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>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
eliminate(tcx, body);
|
eliminate(tcx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
|
||||||
simplify_cfg(body);
|
simplify_cfg(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OptApplier<'tcx> {
|
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>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
deref_finder(tcx, body);
|
deref_finder(tcx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
|
||||||
|
|
||||||
trace!(round_count);
|
trace!(round_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[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 run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
|
pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> {
|
||||||
|
|
|
@ -227,6 +227,10 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
|
||||||
simplify_cfg(body);
|
simplify_cfg(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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);
|
elaborate_patch.apply(body);
|
||||||
deref_finder(tcx, 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
|
/// 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.
|
// statements.
|
||||||
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
|
StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newtype_index! {
|
newtype_index! {
|
||||||
|
|
|
@ -53,4 +53,8 @@ impl<'tcx> MirPass<'tcx> for ImpossiblePredicates {
|
||||||
body.local_decls.raw.truncate(body.arg_count + 1);
|
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);
|
deref_finder(tcx, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForceInline;
|
pub struct ForceInline;
|
||||||
|
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
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 span = trace_span!("force_inline", body = %tcx.def_path_str(body.source.def_id()));
|
||||||
let _guard = span.enter();
|
let _guard = span.enter();
|
||||||
|
|
|
@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
|
||||||
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
|
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstSimplifyContext<'a, 'tcx> {
|
struct InstSimplifyContext<'a, 'tcx> {
|
||||||
|
|
|
@ -105,6 +105,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
|
||||||
}
|
}
|
||||||
OpportunitySet::new(body, opportunities).apply(body);
|
OpportunitySet::new(body, opportunities).apply(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -200,6 +200,10 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumSizeOpt {
|
impl EnumSizeOpt {
|
||||||
|
|
|
@ -388,6 +388,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
|
||||||
&Lint(sanity_check::SanityCheck),
|
&Lint(sanity_check::SanityCheck),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
|
pm::Optimizations::Allowed,
|
||||||
);
|
);
|
||||||
tcx.alloc_steal_mir(body)
|
tcx.alloc_steal_mir(body)
|
||||||
}
|
}
|
||||||
|
@ -440,6 +441,7 @@ fn mir_promoted(
|
||||||
&mut body,
|
&mut body,
|
||||||
&[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
|
&[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
|
||||||
Some(MirPhase::Analysis(AnalysisPhase::Initial)),
|
Some(MirPhase::Analysis(AnalysisPhase::Initial)),
|
||||||
|
pm::Optimizations::Allowed,
|
||||||
);
|
);
|
||||||
|
|
||||||
lint_tail_expr_drop_order::run_lint(tcx, def, &body);
|
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);
|
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
|
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();
|
let is_fn_like = tcx.def_kind(def).is_fn_like();
|
||||||
if is_fn_like {
|
if is_fn_like {
|
||||||
// Do not compute the mir call graph without said call graph actually being used.
|
// 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())
|
|| 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()));
|
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),
|
&Lint(post_drop_elaboration::CheckLiveDrops),
|
||||||
],
|
],
|
||||||
None,
|
None,
|
||||||
|
pm::Optimizations::Allowed,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,7 +560,13 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
&deref_separator::Derefer,
|
&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.
|
/// 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,
|
&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
|
// Clear this by anticipation. Optimizations and runtime MIR have no reason to look
|
||||||
// into this information, which is meant for borrowck diagnostics.
|
// 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)
|
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.
|
// The main optimizations that we do on MIR.
|
||||||
pm::run_passes(
|
pm::run_passes(
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -683,6 +707,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
&dump_mir::Marker("PreCodegen"),
|
&dump_mir::Marker("PreCodegen"),
|
||||||
],
|
],
|
||||||
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
|
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);
|
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) {
|
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);
|
simplify_cfg(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SimplifyMatch<'tcx> {
|
trait SimplifyMatch<'tcx> {
|
||||||
|
|
|
@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
body.set_mentioned_items(visitor.mentioned_items);
|
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
|
// 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)
|
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.
|
// The return place is always mutable.
|
||||||
ret_decl.mutability = Mutability::Mut;
|
ret_decl.mutability = Mutability::Mut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MIR that is eligible for the NRVO must fulfill two conditions:
|
/// 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 {
|
fn is_mir_dump_enabled(&self) -> bool {
|
||||||
true
|
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
|
/// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is
|
||||||
|
@ -134,6 +139,10 @@ where
|
||||||
fn is_mir_dump_enabled(&self) -> bool {
|
fn is_mir_dump_enabled(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct WithMinOptLevel<T>(pub u32, pub T);
|
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>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
self.1.run_pass(tcx, body)
|
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
|
/// 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>],
|
passes: &[&dyn MirPass<'tcx>],
|
||||||
phase_change: Option<MirPhase>,
|
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
|
/// 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>,
|
body: &mut Body<'tcx>,
|
||||||
passes: &[&dyn MirPass<'tcx>],
|
passes: &[&dyn MirPass<'tcx>],
|
||||||
phase_change: Option<MirPhase>,
|
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
|
where
|
||||||
P: MirPass<'tcx> + ?Sized,
|
P: MirPass<'tcx> + ?Sized,
|
||||||
{
|
{
|
||||||
|
@ -196,7 +223,8 @@ where
|
||||||
);
|
);
|
||||||
*polarity
|
*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>(
|
fn run_passes_inner<'tcx>(
|
||||||
|
@ -205,6 +233,7 @@ fn run_passes_inner<'tcx>(
|
||||||
passes: &[&dyn MirPass<'tcx>],
|
passes: &[&dyn MirPass<'tcx>],
|
||||||
phase_change: Option<MirPhase>,
|
phase_change: Option<MirPhase>,
|
||||||
validate_each: bool,
|
validate_each: bool,
|
||||||
|
optimizations: Optimizations,
|
||||||
) {
|
) {
|
||||||
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||||
trace!(?overridden_passes);
|
trace!(?overridden_passes);
|
||||||
|
@ -243,7 +272,7 @@ fn run_passes_inner<'tcx>(
|
||||||
for pass in passes {
|
for pass in passes {
|
||||||
let name = pass.name();
|
let name = pass.name();
|
||||||
|
|
||||||
if !should_run_pass(tcx, *pass) {
|
if !should_run_pass(tcx, *pass, optimizations) {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize {
|
||||||
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
|
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
|
||||||
PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
|
PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PostAnalysisNormalizeVisitor<'tcx> {
|
struct PostAnalysisNormalizeVisitor<'tcx> {
|
||||||
|
|
|
@ -35,6 +35,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
|
||||||
|
|
||||||
permute(body.basic_blocks.as_mut(), &updater.map);
|
permute(body.basic_blocks.as_mut(), &updater.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rearranges the locals into *use* order.
|
/// Rearranges the locals into *use* order.
|
||||||
|
@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
|
||||||
|
|
||||||
permute(&mut body.local_decls, &updater.map);
|
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>) {
|
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);
|
let promoted = promote_candidates(body, tcx, temps, promotable_candidates);
|
||||||
self.promoted_fragments.set(promoted);
|
self.promoted_fragments.set(promoted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State of a temporary during collection and promotion.
|
/// 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());
|
debug!(def_id = ?body.source.def_id());
|
||||||
while propagate_ssa(tcx, body) {}
|
while propagate_ssa(tcx, body) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
|
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);
|
debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoveNoopLandingPads {
|
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 };
|
block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_needs_drop_and_init<'tcx>(
|
fn is_needs_drop_and_init<'tcx>(
|
||||||
|
|
|
@ -38,4 +38,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
|
||||||
simplify_cfg(body);
|
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);
|
replacer.visit_basic_block_data(bb, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Replacer<'a, 'tcx> {
|
struct Replacer<'a, 'tcx> {
|
||||||
|
|
|
@ -119,6 +119,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
|
||||||
&add_call_guards::CriticalCallEdges,
|
&add_call_guards::CriticalCallEdges,
|
||||||
],
|
],
|
||||||
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
|
Some(MirPhase::Runtime(RuntimePhase::Optimized)),
|
||||||
|
pm::Optimizations::Allowed,
|
||||||
);
|
);
|
||||||
|
|
||||||
return body;
|
return body;
|
||||||
|
|
|
@ -83,6 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
|
||||||
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
|
debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
|
||||||
simplify_cfg(body);
|
simplify_cfg(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CfgSimplifier<'a, 'tcx> {
|
struct CfgSimplifier<'a, 'tcx> {
|
||||||
|
@ -405,6 +409,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
|
||||||
body.local_decls.shrink_to_fit();
|
body.local_decls.shrink_to_fit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
|
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);
|
body.basic_blocks_mut()[idx].statements.insert(0, stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OptimizationFinder<'a, 'tcx> {
|
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)]
|
#[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.
|
/// 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);
|
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();
|
body.basic_blocks_mut()[bb].statements.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_required(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return whether the current terminator is fully unreachable.
|
/// 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> {
|
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