diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c8f388bfa1d5a..665a0b22b47c3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -956,6 +956,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_terminator(bx, bb, data.terminator()); } + pub fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { + let mut bx = self.build_block(bb); + debug!("codegen_block_as_unreachable({:?})", bb); + bx.unreachable(); + } + fn codegen_terminator( &mut self, mut bx: Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1ef863e84af7f..60b377bbc9cc6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -240,10 +240,19 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut bx); + let reachable_blocks = mir.reachable_blocks_in_mono(cx.tcx(), instance); + // Codegen the body of each block using reverse postorder // FIXME(eddyb) reuse RPO iterator between `analysis` and this. for (bb, _) in traversal::reverse_postorder(&mir) { - fx.codegen_block(bb); + if reachable_blocks.contains(bb) { + fx.codegen_block(bb); + } else { + // This may have references to things we didn't monomorphize, so we + // don't actually codegen the body. We still create the block so + // terminators in other blocks can reference it without worry. + fx.codegen_block_as_unreachable(bb); + } } // For backends that support CFI using type membership (i.e., testing whether a given pointer diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 253ac266bedaa..d5814a1c08613 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -11,7 +11,7 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, Instance, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; @@ -23,7 +23,7 @@ pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphSuccessors}; -use rustc_index::bit_set::BitMatrix; +use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; @@ -517,6 +517,73 @@ impl<'tcx> Body<'tcx> { pub fn generator_kind(&self) -> Option { self.generator.as_ref().map(|generator| generator.generator_kind) } + + /// Finds which basic blocks are actually reachable for a specific + /// monomorphization of this body. + /// + /// This is allowed to have false positives; just because this says a block + /// is reachable doesn't mean that's necessarily true. It's thus always + /// legal for this to return a filled set. + /// + /// Regardless, the [`BitSet::domain_size`] of the returned set will always + /// exactly match the number of blocks in the body so that `contains` + /// checks can be done without worrying about panicking. + /// + /// The main case this supports is filtering out `if ::CONST` + /// bodies that can't be removed in generic MIR, but *can* be removed once + /// the specific `T` is known. + /// + /// This is used in the monomorphization collector as well as in codegen. + pub fn reachable_blocks_in_mono( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + ) -> BitSet { + if instance.substs.is_noop() { + // If it's non-generic, then mir-opt const prop has already run, meaning it's + // probably not worth doing any further filtering. So call everything reachable. + return BitSet::new_filled(self.basic_blocks().len()); + } + + let mut set = BitSet::new_empty(self.basic_blocks().len()); + self.reachable_blocks_in_mono_from(tcx, instance, &mut set, START_BLOCK); + set + } + + fn reachable_blocks_in_mono_from( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + set: &mut BitSet, + bb: BasicBlock, + ) { + if !set.insert(bb) { + return; + } + + let data = &self.basic_blocks()[bb]; + + if let TerminatorKind::SwitchInt { + discr: Operand::Constant(constant), + switch_ty, + targets, + } = &data.terminator().kind + { + let env = ty::ParamEnv::reveal_all(); + let mono_literal = + instance.subst_mir_and_normalize_erasing_regions(tcx, env, constant.literal); + if let Some(bits) = mono_literal.try_eval_bits(tcx, env, switch_ty) { + let target = targets.target_for_value(bits); + return self.reachable_blocks_in_mono_from(tcx, instance, set, target); + } else { + bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); + } + } + + for &target in data.terminator().successors() { + self.reachable_blocks_in_mono_from(tcx, instance, set, target); + } + } } #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)] @@ -1504,6 +1571,7 @@ impl Statement<'_> { } /// Changes a statement to a nop and returns the original statement. + #[must_use = "If you don't need the statement, use `make_nop` instead"] pub fn replace_nop(&mut self) -> Self { Statement { source_info: self.source_info, diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index e78b6fd092de2..e33fb1acb6e60 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -78,6 +78,13 @@ impl SwitchTargets { pub fn all_targets_mut(&mut self) -> &mut [BasicBlock] { &mut self.targets } + + /// Finds the `BasicBlock` to which this `SwitchInt` will branch given the + /// specific value. This cannot fail, as it'll return the `otherwise` + /// branch if there's not a specific match for the value. + pub fn target_for_value(&self, value: u128) -> BasicBlock { + self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) + } } pub struct SwitchTargetsIter<'a> { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f9ef314627807..d4337385738ff 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -71,6 +71,7 @@ mod shim; mod simplify; mod simplify_branches; mod simplify_comparison_integral; +mod simplify_if_const; mod simplify_try; mod uninhabited_enum_branching; mod unreachable_prop; @@ -456,6 +457,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ // Remove all things only needed by analysis + &simplify_if_const::SimplifyIfConst, &simplify_branches::SimplifyBranches::new("initial"), &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index df90cfa318df0..d8fc4aa9a6a7f 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -34,15 +34,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { } => { let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); if let Some(constant) = constant { - let otherwise = targets.otherwise(); - let mut ret = TerminatorKind::Goto { target: otherwise }; - for (v, t) in targets.iter() { - if v == constant { - ret = TerminatorKind::Goto { target: t }; - break; - } - } - ret + let target = targets.target_for_value(constant); + TerminatorKind::Goto { target } } else { continue; } diff --git a/compiler/rustc_mir_transform/src/simplify_if_const.rs b/compiler/rustc_mir_transform/src/simplify_if_const.rs new file mode 100644 index 0000000000000..ae61e75797ed8 --- /dev/null +++ b/compiler/rustc_mir_transform/src/simplify_if_const.rs @@ -0,0 +1,76 @@ +//! A pass that simplifies branches when their condition is known. + +use crate::MirPass; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +/// The lowering for `if CONST` produces +/// ``` +/// _1 = Const(...); +/// switchInt (move _1) +/// ``` +/// so this pass replaces that with +/// ``` +/// switchInt (Const(...)) +/// ``` +/// so that further MIR consumers can special-case it more easily. +/// +/// Unlike ConstProp, this supports generic constants too, not just concrete ones. +pub struct SimplifyIfConst; + +impl<'tcx> MirPass<'tcx> for SimplifyIfConst { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + for block in body.basic_blocks_mut() { + simplify_assign_move_switch(tcx, block); + } + } +} + +fn simplify_assign_move_switch(tcx: TyCtxt<'_>, block: &mut BasicBlockData<'_>) { + let Some(Terminator { kind: TerminatorKind::SwitchInt { discr: switch_desc, ..}, ..}) = + &mut block.terminator + else { return }; + + let &mut Operand::Move(switch_place) = &mut*switch_desc + else { return }; + + let Some(switch_local) = switch_place.as_local() + else { return }; + + let Some(last_statement) = block.statements.last_mut() + else { return }; + + let StatementKind::Assign(boxed_place_rvalue) = &last_statement.kind + else { return }; + + let Some(assigned_local) = boxed_place_rvalue.0.as_local() + else { return }; + + if switch_local != assigned_local { + return; + } + + if !matches!(boxed_place_rvalue.1, Rvalue::Use(Operand::Constant(_))) { + return; + } + + let should_optimize = tcx.consider_optimizing(|| { + format!( + "SimplifyBranches - Assignment: {:?} SourceInfo: {:?}", + boxed_place_rvalue, last_statement.source_info + ) + }); + + if should_optimize { + let Some(last_statement) = block.statements.pop() + else { bug!("Somehow the statement disappeared?"); }; + + let StatementKind::Assign(boxed_place_rvalue) = last_statement.kind + else { bug!("Somehow it's not an assignment any more?"); }; + + let Rvalue::Use(assigned_constant @ Operand::Constant(_)) = boxed_place_rvalue.1 + else { bug!("Somehow it's not a use of a constant any more?"); }; + + *switch_desc = assigned_constant; + } +} diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 59988e69b5d3a..c2e1062cdbbe2 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -185,7 +185,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; -use rustc_index::bit_set::GrowableBitSet; +use rustc_index::bit_set::{BitSet, GrowableBitSet}; use rustc_middle::mir::interpret::{AllocId, ConstValue}; use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; @@ -608,6 +608,7 @@ struct MirNeighborCollector<'a, 'tcx> { body: &'a mir::Body<'tcx>, output: &'a mut Vec>>, instance: Instance<'tcx>, + reachable_blocks: BitSet, } impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> { @@ -625,6 +626,14 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> { } impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { + fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) { + if self.reachable_blocks.contains(block) { + self.super_basic_block_data(block, data); + } else { + debug!("skipping mono-unreachable basic block {:?}", block); + } + } + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { debug!("visiting rvalue {:?}", *rvalue); @@ -1395,7 +1404,10 @@ fn collect_neighbours<'tcx>( debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); - MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body); + let reachable_blocks = body.reachable_blocks_in_mono(tcx, instance); + let mut collector = + MirNeighborCollector { tcx, body: &body, output, instance, reachable_blocks }; + collector.visit_body(&body); } fn collect_const_value<'tcx>( diff --git a/library/alloc/src/vec/source_iter_marker.rs b/library/alloc/src/vec/source_iter_marker.rs index 6e78534cf5b10..1c7417375e512 100644 --- a/library/alloc/src/vec/source_iter_marker.rs +++ b/library/alloc/src/vec/source_iter_marker.rs @@ -21,12 +21,7 @@ where // a) no ZSTs as there would be no allocation to reuse and pointer arithmetic would panic // b) size match as required by Alloc contract // c) alignments match as required by Alloc contract - if mem::size_of::() == 0 - || mem::size_of::() - != mem::size_of::<<::Source as AsIntoIter>::Item>() - || mem::align_of::() - != mem::align_of::<<::Source as AsIntoIter>::Item>() - { + if ::MATCHES { // fallback to more generic implementations return SpecFromIterNested::from_iter(iterator); } @@ -154,3 +149,18 @@ where len } } + +trait LayoutMatcher { + type IN; + const MATCHES: bool; +} + +impl LayoutMatcher for I +where + I: Iterator + SourceIter, +{ + type IN = <::Source as AsIntoIter>::Item; + const MATCHES: bool = mem::size_of::() == 0 + || mem::size_of::() != mem::size_of::() + || mem::align_of::() != mem::align_of::(); +} diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8ab72e6aeeafa..f42c7fd34be8e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -430,6 +430,13 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { #[inline] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] pub(crate) const unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { + trait TypeSizeCheck { + const IS_CHUNK_SIZE_OR_LARGER: bool; + } + impl TypeSizeCheck for T { + const IS_CHUNK_SIZE_OR_LARGER: bool = mem::size_of::() >= 32; + } + // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary // reinterpretation of values as (chunkable) byte arrays, and the loop in the // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back @@ -442,7 +449,7 @@ pub(crate) const unsafe fn swap_nonoverlapping_one(x: *mut T, y: *mut T) { { // Only apply the block optimization in `swap_nonoverlapping_bytes` for types // at least as large as the block size, to avoid pessimizing codegen. - if mem::size_of::() >= 32 { + if T::IS_CHUNK_SIZE_OR_LARGER { // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`. unsafe { swap_nonoverlapping(x, y, 1) }; return; diff --git a/src/test/codegen/skip-mono-inside-if-false.rs b/src/test/codegen/skip-mono-inside-if-false.rs new file mode 100644 index 0000000000000..2557daa91043c --- /dev/null +++ b/src/test/codegen/skip-mono-inside-if-false.rs @@ -0,0 +1,43 @@ +// compile-flags: -O -C no-prepopulate-passes + +#![crate_type = "lib"] + +#[no_mangle] +pub fn demo_for_i32() { + generic_impl::(); +} + +// Two important things here: +// - We replace the "then" block with `unreachable` to avoid linking problems +// - We neither declare nor define the `big_impl` that said block "calls". + +// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl +// CHECK: start: +// CHECK-NEXT: br i1 false, label %[[THEN_BRANCH:bb[0-9]+]], label %[[ELSE_BRANCH:bb[0-9]+]] +// CHECK: [[ELSE_BRANCH]]: +// CHECK-NEXT: call skip_mono_inside_if_false::small_impl +// CHECK: [[THEN_BRANCH]]: +// CHECK-NEXT: unreachable + +// CHECK-NOT: @_ZN25skip_mono_inside_if_false8big_impl +// CHECK: define internal void @_ZN25skip_mono_inside_if_false10small_impl +// CHECK-NOT: @_ZN25skip_mono_inside_if_false8big_impl + +fn generic_impl() { + trait MagicTrait { + const IS_BIG: bool; + } + impl MagicTrait for T { + const IS_BIG: bool = std::mem::size_of::() > 10; + } + if T::IS_BIG { + big_impl::(); + } else { + small_impl::(); + } +} + +#[inline(never)] +fn small_impl() {} +#[inline(never)] +fn big_impl() {} diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control-flow-simplification.rs index aa4ce19f620fe..bcd205e195aa4 100644 --- a/src/test/mir-opt/const_prop/control-flow-simplification.rs +++ b/src/test/mir-opt/const_prop/control-flow-simplification.rs @@ -1,15 +1,15 @@ // compile-flags: -Zmir-opt-level=1 -trait NeedsDrop:Sized{ - const NEEDS:bool=std::mem::needs_drop::(); +trait HasSize: Sized { + const BYTES: usize = std::mem::size_of::(); } -impl NeedsDrop for This{} +impl HasSize for This{} // EMIT_MIR control_flow_simplification.hello.ConstProp.diff // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir fn hello(){ - if ::NEEDS { + if ::BYTES > 10 { panic!() } } diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index 1eb40e50d7aa0..b4416529004d1 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -3,15 +3,15 @@ fn hello() -> () { let mut _0: (); // return place in scope 0 at $DIR/control-flow-simplification.rs:11:14: 11:14 - let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 + let mut _1: bool; // in scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 let mut _2: !; // in scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL bb0: { - StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 -- _1 = const ::NEEDS; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 -- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 -+ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 -+ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21 + StorageLive(_1); // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 +- _1 = Gt(const ::BYTES, const 10_usize); // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 +- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 ++ _1 = const false; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 ++ switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:26 } bb1: { diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff index 0511b59cf013a..51bd1b7117186 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff @@ -1,83 +1,89 @@ - // MIR for `match_nested_if` before MatchBranchSimplification + // MIR for `match_nested_if` after MatchBranchSimplification - + fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 + let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 + let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12 } - + bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- } -- -- bb1: { -- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 + StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + _4 = unknown() -> bb1; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + // mir::Constant + // + span: $DIR/matches_reduce_branches.rs:41:24: 41:31 + // + literal: Const { ty: fn() -> bool {unknown}, val: Value(Scalar()) } + } + + bb1: { +- switchInt(move _4) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 - } -- +- - bb2: { -- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:36: 41:40 +- goto -> bb4; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } -- +- - bb3: { -+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 -- switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:50: 41:55 +- goto -> bb4; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } -- +- - bb4: { -- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:50: 41:55 ++ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:56: 41:57 +- switchInt(move _3) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } -- +- - bb5: { -- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 +- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:60: 41:64 +- goto -> bb7; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 - } -- +- - bb6: { -+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76 -- switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 +- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:74: 41:79 +- goto -> bb7; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 - } -- +- - bb7: { -+ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:74: 41:79 ++ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:80: 41:81 +- switchInt(move _2) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 +- } +- +- bb8: { ++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 ++ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 - _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 +- goto -> bb10; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 - } -- -- bb8: { +- +- bb9: { - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 - _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 +- goto -> bb10; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 - } -- -- bb9: { +- +- bb10: { + _1 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2 diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff index 0511b59cf013a..2b0d4f5408a57 100644 --- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff +++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff @@ -4,80 +4,86 @@ fn match_nested_if() -> bool { let mut _0: bool; // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29 let _1: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 + let mut _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 + let mut _3: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + let mut _4: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ let mut _5: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ let mut _6: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 scope 1 { debug val => _1; // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12 } bb0: { StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12 - StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 - StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - _4 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -- } -- -- bb1: { -- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 + StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 + StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + _4 = unknown() -> bb1; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + // mir::Constant + // + span: $DIR/matches_reduce_branches.rs:41:24: 41:31 + // + literal: Const { ty: fn() -> bool {unknown}, val: Value(Scalar()) } + } + + bb1: { +- switchInt(move _4) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 - } - - bb2: { -- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -- goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- _3 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:36: 41:40 +- goto -> bb4; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } - - bb3: { -+ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 -+ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50 -+ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28 - StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52 -- switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 +- _3 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:50: 41:55 +- goto -> bb4; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } - - bb4: { -- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ _5 = move _4; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 ++ _3 = Ne(_5, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:50: 41:55 ++ StorageDead(_5); // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:33 + StorageDead(_4); // scope 0 at $DIR/matches_reduce_branches.rs:41:56: 41:57 +- switchInt(move _3) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 - } - - bb5: { -- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 +- _2 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:41:60: 41:64 +- goto -> bb7; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 - } - - bb6: { -+ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 -+ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74 -+ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52 - StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76 -- switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 +- _2 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:41:74: 41:79 +- goto -> bb7; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 - } - - bb7: { -+ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 -+ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageLive(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ _6 = move _3; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 ++ _2 = Ne(_6, const false); // scope 0 at $DIR/matches_reduce_branches.rs:41:74: 41:79 ++ StorageDead(_6); // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:57 + StorageDead(_3); // scope 0 at $DIR/matches_reduce_branches.rs:41:80: 41:81 +- switchInt(move _2) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 +- } +- +- bb8: { ++ StorageLive(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 ++ _7 = move _2; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 - _1 = const true; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 +- goto -> bb10; // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17 - } - -- bb8: { +- bb9: { - StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10 - _1 = const false; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -- goto -> bb9; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 +- goto -> bb10; // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 - } - -- bb9: { +- bb10: { + _1 = Ne(_7, const false); // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19 -+ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76 ++ StorageDead(_7); // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:81 _0 = _1; // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8 StorageDead(_1); // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2 return; // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2 diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs index 51be3884d48dd..ca6fbd7f06492 100644 --- a/src/test/mir-opt/matches_reduce_branches.rs +++ b/src/test/mir-opt/matches_reduce_branches.rs @@ -38,7 +38,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) { fn match_nested_if() -> bool { let val = match () { - () if if if if true { true } else { false } { true } else { false } { + () if if if if unknown() { true } else { false } { true } else { false } { true } else { false @@ -57,3 +57,6 @@ fn main() { let _ = bar(0); let _ = match_nested_if(); } + +#[inline(never)] +fn unknown() -> bool { unimplemented!() } diff --git a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyBranches-initial.diff similarity index 57% rename from src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff rename to src/test/mir-opt/simplify_if.main.SimplifyBranches-initial.diff index def6f835131c9..a58c64715b634 100644 --- a/src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/simplify_if.main.SimplifyBranches-initial.diff @@ -1,40 +1,43 @@ -- // MIR for `main` before SimplifyBranches-after-const-prop -+ // MIR for `main` after SimplifyBranches-after-const-prop +- // MIR for `main` before SimplifyBranches-initial ++ // MIR for `main` after SimplifyBranches-initial fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify_if.rs:5:11: 5:11 - let mut _1: bool; // in scope 0 at $DIR/simplify_if.rs:6:8: 6:13 - let _2: (); // in scope 0 at $DIR/simplify_if.rs:7:9: 7:15 + let mut _0: (); // return place in scope 0 at $DIR/simplify_if.rs:7:11: 7:11 + let mut _1: bool; // in scope 0 at $DIR/simplify_if.rs:8:8: 8:13 + let _2: (); // in scope 0 at $DIR/simplify_if.rs:9:9: 9:15 bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify_if.rs:6:8: 6:13 - _1 = const false; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13 -- switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13 -+ goto -> bb3; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13 + StorageLive(_1); // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 +- switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 ++ goto -> bb3; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 } bb1: { - StorageLive(_2); // scope 0 at $DIR/simplify_if.rs:7:9: 7:15 - _2 = noop() -> bb2; // scope 0 at $DIR/simplify_if.rs:7:9: 7:15 + StorageLive(_2); // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 + _2 = noop() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 // mir::Constant - // + span: $DIR/simplify_if.rs:7:9: 7:13 + // + span: $DIR/simplify_if.rs:9:9: 9:13 // + literal: Const { ty: fn() {noop}, val: Value(Scalar()) } } bb2: { - StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:7:15: 7:16 - nop; // scope 0 at $DIR/simplify_if.rs:6:14: 8:6 - goto -> bb4; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6 + StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:9:15: 9:16 + _0 = const (); // scope 0 at $DIR/simplify_if.rs:8:14: 10:6 + goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 } bb3: { - nop; // scope 0 at $DIR/simplify_if.rs:8:6: 8:6 - goto -> bb4; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6 + _0 = const (); // scope 0 at $DIR/simplify_if.rs:10:6: 10:6 + goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 } bb4: { - StorageDead(_1); // scope 0 at $DIR/simplify_if.rs:8:5: 8:6 - return; // scope 0 at $DIR/simplify_if.rs:9:2: 9:2 + StorageDead(_1); // scope 0 at $DIR/simplify_if.rs:10:5: 10:6 + return; // scope 0 at $DIR/simplify_if.rs:11:2: 11:2 + } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/simplify_if.rs:7:1: 11:2 } } diff --git a/src/test/mir-opt/simplify_if.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_if.main.SimplifyCfg-early-opt.diff new file mode 100644 index 0000000000000..7ffe96e0eeed3 --- /dev/null +++ b/src/test/mir-opt/simplify_if.main.SimplifyCfg-early-opt.diff @@ -0,0 +1,42 @@ +- // MIR for `main` before SimplifyCfg-early-opt ++ // MIR for `main` after SimplifyCfg-early-opt + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify_if.rs:7:11: 7:11 + let mut _1: bool; // in scope 0 at $DIR/simplify_if.rs:8:8: 8:13 + let _2: (); // in scope 0 at $DIR/simplify_if.rs:9:9: 9:15 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 +- goto -> bb3; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 +- } +- +- bb1: { +- StorageLive(_2); // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 +- _2 = noop() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 +- // mir::Constant +- // + span: $DIR/simplify_if.rs:9:9: 9:13 +- // + literal: Const { ty: fn() {noop}, val: Value(Scalar()) } +- } +- +- bb2: { +- StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:9:15: 9:16 +- _0 = const (); // scope 0 at $DIR/simplify_if.rs:8:14: 10:6 +- goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 +- } +- +- bb3: { + _0 = const (); // scope 0 at $DIR/simplify_if.rs:10:6: 10:6 +- goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 +- } +- +- bb4: { + StorageDead(_1); // scope 0 at $DIR/simplify_if.rs:10:5: 10:6 + return; // scope 0 at $DIR/simplify_if.rs:11:2: 11:2 +- } +- +- bb5 (cleanup): { +- resume; // scope 0 at $DIR/simplify_if.rs:7:1: 11:2 + } + } + diff --git a/src/test/mir-opt/simplify_if.main.SimplifyIfConst.diff b/src/test/mir-opt/simplify_if.main.SimplifyIfConst.diff new file mode 100644 index 0000000000000..eefd764e6bb13 --- /dev/null +++ b/src/test/mir-opt/simplify_if.main.SimplifyIfConst.diff @@ -0,0 +1,44 @@ +- // MIR for `main` before SimplifyIfConst ++ // MIR for `main` after SimplifyIfConst + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify_if.rs:7:11: 7:11 + let mut _1: bool; // in scope 0 at $DIR/simplify_if.rs:8:8: 8:13 + let _2: (); // in scope 0 at $DIR/simplify_if.rs:9:9: 9:15 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 +- _1 = const false; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 +- switchInt(move _1) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 ++ switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:8:8: 8:13 + } + + bb1: { + StorageLive(_2); // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 + _2 = noop() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_if.rs:9:9: 9:15 + // mir::Constant + // + span: $DIR/simplify_if.rs:9:9: 9:13 + // + literal: Const { ty: fn() {noop}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:9:15: 9:16 + _0 = const (); // scope 0 at $DIR/simplify_if.rs:8:14: 10:6 + goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 + } + + bb3: { + _0 = const (); // scope 0 at $DIR/simplify_if.rs:10:6: 10:6 + goto -> bb4; // scope 0 at $DIR/simplify_if.rs:8:5: 10:6 + } + + bb4: { + StorageDead(_1); // scope 0 at $DIR/simplify_if.rs:10:5: 10:6 + return; // scope 0 at $DIR/simplify_if.rs:11:2: 11:2 + } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/simplify_if.rs:7:1: 11:2 + } + } + diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index 67b2027b710c9..6ba3b5aa55075 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -1,7 +1,9 @@ #[inline(never)] fn noop() {} -// EMIT_MIR simplify_if.main.SimplifyBranches-after-const-prop.diff +// EMIT_MIR simplify_if.main.SimplifyIfConst.diff +// EMIT_MIR simplify_if.main.SimplifyBranches-initial.diff +// EMIT_MIR simplify_if.main.SimplifyCfg-early-opt.diff fn main() { if false { noop(); diff --git a/src/test/mir-opt/simplify_if_generic_constant.rs b/src/test/mir-opt/simplify_if_generic_constant.rs new file mode 100644 index 0000000000000..159802bbe2826 --- /dev/null +++ b/src/test/mir-opt/simplify_if_generic_constant.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] + +pub trait HasBoolConst { + const B: bool; +} + +// EMIT_MIR simplify_if_generic_constant.use_associated_const.SimplifyIfConst.diff +pub fn use_associated_const() -> u8 { + if ::B { + 13 + } else { + 42 + } +} diff --git a/src/test/mir-opt/simplify_if_generic_constant.use_associated_const.SimplifyIfConst.diff b/src/test/mir-opt/simplify_if_generic_constant.use_associated_const.SimplifyIfConst.diff new file mode 100644 index 0000000000000..2a006c541cd2c --- /dev/null +++ b/src/test/mir-opt/simplify_if_generic_constant.use_associated_const.SimplifyIfConst.diff @@ -0,0 +1,30 @@ +- // MIR for `use_associated_const` before SimplifyIfConst ++ // MIR for `use_associated_const` after SimplifyIfConst + + fn use_associated_const() -> u8 { + let mut _0: u8; // return place in scope 0 at $DIR/simplify_if_generic_constant.rs:8:51: 8:53 + let mut _1: bool; // in scope 0 at $DIR/simplify_if_generic_constant.rs:9:8: 9:30 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/simplify_if_generic_constant.rs:9:8: 9:30 +- _1 = const ::B; // scope 0 at $DIR/simplify_if_generic_constant.rs:9:8: 9:30 +- switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify_if_generic_constant.rs:9:8: 9:30 ++ switchInt(const ::B) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify_if_generic_constant.rs:9:8: 9:30 + } + + bb1: { + _0 = const 13_u8; // scope 0 at $DIR/simplify_if_generic_constant.rs:10:9: 10:11 + goto -> bb3; // scope 0 at $DIR/simplify_if_generic_constant.rs:9:5: 13:6 + } + + bb2: { + _0 = const 42_u8; // scope 0 at $DIR/simplify_if_generic_constant.rs:12:9: 12:11 + goto -> bb3; // scope 0 at $DIR/simplify_if_generic_constant.rs:9:5: 13:6 + } + + bb3: { + StorageDead(_1); // scope 0 at $DIR/simplify_if_generic_constant.rs:13:5: 13:6 + return; // scope 0 at $DIR/simplify_if_generic_constant.rs:14:2: 14:2 + } + } + diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff index 63356a400d29a..9f5ab875b6f94 100644 --- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff @@ -8,7 +8,7 @@ let _3: Empty; // in scope 0 at $DIR/unreachable.rs:9:17: 9:19 let mut _4: i32; // in scope 0 at $DIR/unreachable.rs:10:13: 10:19 let _5: (); // in scope 0 at $DIR/unreachable.rs:12:9: 16:10 - let mut _6: bool; // in scope 0 at $DIR/unreachable.rs:12:12: 12:16 + let mut _6: bool; // in scope 0 at $DIR/unreachable.rs:12:12: 12:21 let mut _7: !; // in scope 0 at $DIR/unreachable.rs:18:9: 18:21 scope 1 { debug _x => _3; // in scope 1 at $DIR/unreachable.rs:9:17: 9:19 @@ -27,40 +27,47 @@ bb1: { _2 = discriminant(_1); // scope 0 at $DIR/unreachable.rs:9:12: 9:20 -- switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable.rs:9:12: 9:20 -+ goto -> bb2; // scope 0 at $DIR/unreachable.rs:9:12: 9:20 +- switchInt(move _2) -> [1_isize: bb2, otherwise: bb7]; // scope 0 at $DIR/unreachable.rs:9:12: 9:20 ++ switchInt(move _2) -> [1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/unreachable.rs:9:12: 9:20 } bb2: { -- StorageLive(_3); // scope 0 at $DIR/unreachable.rs:9:17: 9:19 -- _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable.rs:9:17: 9:19 -- StorageLive(_4); // scope 0 at $DIR/unreachable.rs:10:13: 10:19 -- StorageLive(_5); // scope 2 at $DIR/unreachable.rs:12:9: 16:10 -- StorageLive(_6); // scope 2 at $DIR/unreachable.rs:12:12: 12:16 -- _6 = const true; // scope 2 at $DIR/unreachable.rs:12:12: 12:16 -- switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:12:12: 12:16 -- } -- -- bb3: { + StorageLive(_3); // scope 0 at $DIR/unreachable.rs:9:17: 9:19 + _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable.rs:9:17: 9:19 + StorageLive(_4); // scope 0 at $DIR/unreachable.rs:10:13: 10:19 + StorageLive(_5); // scope 2 at $DIR/unreachable.rs:12:9: 16:10 + StorageLive(_6); // scope 2 at $DIR/unreachable.rs:12:12: 12:21 + _6 = unknown() -> bb3; // scope 2 at $DIR/unreachable.rs:12:12: 12:21 + // mir::Constant + // + span: $DIR/unreachable.rs:12:12: 12:19 + // + literal: Const { ty: fn() -> bool {unknown}, val: Value(Scalar()) } + } + + bb3: { +- switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable.rs:12:12: 12:21 ++ unreachable; // scope 2 at $DIR/unreachable.rs:12:12: 12:21 + } + + bb4: { - _4 = const 21_i32; // scope 2 at $DIR/unreachable.rs:13:13: 13:20 -- _5 = const (); // scope 2 at $DIR/unreachable.rs:12:17: 14:10 -- goto -> bb5; // scope 2 at $DIR/unreachable.rs:12:9: 16:10 +- _5 = const (); // scope 2 at $DIR/unreachable.rs:12:22: 14:10 +- goto -> bb6; // scope 2 at $DIR/unreachable.rs:12:9: 16:10 - } - -- bb4: { +- bb5: { - _4 = const 42_i32; // scope 2 at $DIR/unreachable.rs:15:13: 15:20 - _5 = const (); // scope 2 at $DIR/unreachable.rs:14:16: 16:10 -- goto -> bb5; // scope 2 at $DIR/unreachable.rs:12:9: 16:10 +- goto -> bb6; // scope 2 at $DIR/unreachable.rs:12:9: 16:10 - } - -- bb5: { +- bb6: { - StorageDead(_6); // scope 2 at $DIR/unreachable.rs:16:9: 16:10 - StorageDead(_5); // scope 2 at $DIR/unreachable.rs:16:9: 16:10 - StorageLive(_7); // scope 2 at $DIR/unreachable.rs:18:9: 18:21 - unreachable; // scope 2 at $DIR/unreachable.rs:18:15: 18:17 - } - -- bb6: { +- bb7: { _0 = const (); // scope 0 at $DIR/unreachable.rs:19:6: 19:6 StorageDead(_1); // scope 0 at $DIR/unreachable.rs:20:1: 20:2 return; // scope 0 at $DIR/unreachable.rs:20:2: 20:2 diff --git a/src/test/mir-opt/unreachable.rs b/src/test/mir-opt/unreachable.rs index 6098b525b5597..a861c2bb42c8c 100644 --- a/src/test/mir-opt/unreachable.rs +++ b/src/test/mir-opt/unreachable.rs @@ -9,7 +9,7 @@ fn main() { if let Some(_x) = empty() { let mut _y; - if true { + if unknown() { _y = 21; } else { _y = 42; @@ -18,3 +18,6 @@ fn main() { match _x { } } } + +#[inline(never)] +fn unknown() -> bool { unimplemented!() } diff --git a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff index c60997be5d3c3..b544e21a8ea55 100644 --- a/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff @@ -8,7 +8,7 @@ let _3: Empty; // in scope 0 at $DIR/unreachable_asm.rs:11:17: 11:19 let mut _4: i32; // in scope 0 at $DIR/unreachable_asm.rs:12:13: 12:19 let _5: (); // in scope 0 at $DIR/unreachable_asm.rs:14:9: 18:10 - let mut _6: bool; // in scope 0 at $DIR/unreachable_asm.rs:14:12: 14:16 + let mut _6: bool; // in scope 0 at $DIR/unreachable_asm.rs:14:12: 14:21 let _7: (); // in scope 0 at $DIR/unreachable_asm.rs:21:9: 21:37 let mut _8: !; // in scope 0 at $DIR/unreachable_asm.rs:22:9: 22:21 scope 1 { @@ -30,7 +30,7 @@ bb1: { _2 = discriminant(_1); // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20 - switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20 + switchInt(move _2) -> [1_isize: bb2, otherwise: bb7]; // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20 } bb2: { @@ -38,24 +38,30 @@ _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable_asm.rs:11:17: 11:19 StorageLive(_4); // scope 0 at $DIR/unreachable_asm.rs:12:13: 12:19 StorageLive(_5); // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10 - StorageLive(_6); // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16 - _6 = const true; // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16 - switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16 + StorageLive(_6); // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:21 + _6 = unknown() -> bb3; // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:21 + // mir::Constant + // + span: $DIR/unreachable_asm.rs:14:12: 14:19 + // + literal: Const { ty: fn() -> bool {unknown}, val: Value(Scalar()) } } bb3: { - _4 = const 21_i32; // scope 2 at $DIR/unreachable_asm.rs:15:13: 15:20 - _5 = const (); // scope 2 at $DIR/unreachable_asm.rs:14:17: 16:10 - goto -> bb5; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10 + switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:21 } bb4: { + _4 = const 21_i32; // scope 2 at $DIR/unreachable_asm.rs:15:13: 15:20 + _5 = const (); // scope 2 at $DIR/unreachable_asm.rs:14:22: 16:10 + goto -> bb6; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10 + } + + bb5: { _4 = const 42_i32; // scope 2 at $DIR/unreachable_asm.rs:17:13: 17:20 _5 = const (); // scope 2 at $DIR/unreachable_asm.rs:16:16: 18:10 - goto -> bb5; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10 + goto -> bb6; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10 } - bb5: { + bb6: { StorageDead(_6); // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10 StorageDead(_5); // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10 StorageLive(_7); // scope 2 at $DIR/unreachable_asm.rs:21:9: 21:37 @@ -66,7 +72,7 @@ unreachable; // scope 2 at $DIR/unreachable_asm.rs:22:15: 22:17 } - bb6: { + bb7: { _0 = const (); // scope 0 at $DIR/unreachable_asm.rs:23:6: 23:6 StorageDead(_1); // scope 0 at $DIR/unreachable_asm.rs:24:1: 24:2 return; // scope 0 at $DIR/unreachable_asm.rs:24:2: 24:2 diff --git a/src/test/mir-opt/unreachable_asm.rs b/src/test/mir-opt/unreachable_asm.rs index cbef05a3c05cc..04ac3f46dc10e 100644 --- a/src/test/mir-opt/unreachable_asm.rs +++ b/src/test/mir-opt/unreachable_asm.rs @@ -11,7 +11,7 @@ fn main() { if let Some(_x) = empty() { let mut _y; - if true { + if unknown() { _y = 21; } else { _y = 42; @@ -22,3 +22,6 @@ fn main() { match _x { } } } + +#[inline(never)] +fn unknown() -> bool { unimplemented!() } diff --git a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff index 28c5f031dbbe9..04f9029b10052 100644 --- a/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff @@ -8,7 +8,7 @@ let _3: Empty; // in scope 0 at $DIR/unreachable_asm_2.rs:11:17: 11:19 let mut _4: i32; // in scope 0 at $DIR/unreachable_asm_2.rs:12:13: 12:19 let _5: (); // in scope 0 at $DIR/unreachable_asm_2.rs:14:9: 22:10 - let mut _6: bool; // in scope 0 at $DIR/unreachable_asm_2.rs:14:12: 14:16 + let mut _6: bool; // in scope 0 at $DIR/unreachable_asm_2.rs:14:12: 14:21 let _7: (); // in scope 0 at $DIR/unreachable_asm_2.rs:16:13: 16:41 let _8: (); // in scope 0 at $DIR/unreachable_asm_2.rs:20:13: 20:41 let mut _9: !; // in scope 0 at $DIR/unreachable_asm_2.rs:24:9: 24:21 @@ -33,8 +33,8 @@ bb1: { _2 = discriminant(_1); // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20 -- switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20 -+ switchInt(move _2) -> [1_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20 +- switchInt(move _2) -> [1_isize: bb2, otherwise: bb7]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20 ++ switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20 } bb2: { @@ -42,41 +42,47 @@ _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable_asm_2.rs:11:17: 11:19 StorageLive(_4); // scope 0 at $DIR/unreachable_asm_2.rs:12:13: 12:19 StorageLive(_5); // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 - StorageLive(_6); // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16 - _6 = const true; // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16 - switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16 + StorageLive(_6); // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:21 + _6 = unknown() -> bb3; // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:21 + // mir::Constant + // + span: $DIR/unreachable_asm_2.rs:14:12: 14:19 + // + literal: Const { ty: fn() -> bool {unknown}, val: Value(Scalar()) } } bb3: { + switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:21 + } + + bb4: { StorageLive(_7); // scope 2 at $DIR/unreachable_asm_2.rs:16:13: 16:41 llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm_2.rs:16:22: 16:38 _7 = const (); // scope 3 at $DIR/unreachable_asm_2.rs:16:13: 16:41 StorageDead(_7); // scope 2 at $DIR/unreachable_asm_2.rs:16:40: 16:41 _4 = const 21_i32; // scope 2 at $DIR/unreachable_asm_2.rs:17:13: 17:20 - _5 = const (); // scope 2 at $DIR/unreachable_asm_2.rs:14:17: 18:10 -- goto -> bb5; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 + _5 = const (); // scope 2 at $DIR/unreachable_asm_2.rs:14:22: 18:10 +- goto -> bb6; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 + unreachable; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 } - bb4: { + bb5: { StorageLive(_8); // scope 2 at $DIR/unreachable_asm_2.rs:20:13: 20:41 llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:38 _8 = const (); // scope 4 at $DIR/unreachable_asm_2.rs:20:13: 20:41 StorageDead(_8); // scope 2 at $DIR/unreachable_asm_2.rs:20:40: 20:41 _4 = const 42_i32; // scope 2 at $DIR/unreachable_asm_2.rs:21:13: 21:20 _5 = const (); // scope 2 at $DIR/unreachable_asm_2.rs:18:16: 22:10 -- goto -> bb5; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 +- goto -> bb6; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 + unreachable; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10 } - bb5: { + bb6: { - StorageDead(_6); // scope 2 at $DIR/unreachable_asm_2.rs:22:9: 22:10 - StorageDead(_5); // scope 2 at $DIR/unreachable_asm_2.rs:22:9: 22:10 - StorageLive(_9); // scope 2 at $DIR/unreachable_asm_2.rs:24:9: 24:21 - unreachable; // scope 2 at $DIR/unreachable_asm_2.rs:24:15: 24:17 - } - -- bb6: { +- bb7: { _0 = const (); // scope 0 at $DIR/unreachable_asm_2.rs:25:6: 25:6 StorageDead(_1); // scope 0 at $DIR/unreachable_asm_2.rs:26:1: 26:2 return; // scope 0 at $DIR/unreachable_asm_2.rs:26:2: 26:2 diff --git a/src/test/mir-opt/unreachable_asm_2.rs b/src/test/mir-opt/unreachable_asm_2.rs index e0d8e725147a3..eda13e200737d 100644 --- a/src/test/mir-opt/unreachable_asm_2.rs +++ b/src/test/mir-opt/unreachable_asm_2.rs @@ -11,7 +11,7 @@ fn main() { if let Some(_x) = empty() { let mut _y; - if true { + if unknown() { // asm instruction stops unreachable propagation to block bb3. unsafe { llvm_asm!("NOP"); } _y = 21; @@ -24,3 +24,6 @@ fn main() { match _x { } } } + +#[inline(never)] +fn unknown() -> bool { unimplemented!() } diff --git a/src/test/ui/consts/control-flow/drop-fail.precise.stderr b/src/test/ui/consts/control-flow/drop-fail.precise.stderr index 0b0b2443a4a46..578eee5812a1d 100644 --- a/src/test/ui/consts/control-flow/drop-fail.precise.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.precise.stderr @@ -5,7 +5,7 @@ LL | let x = Some(Vec::new()); | ^ constants cannot evaluate destructors error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:39:9 + --> $DIR/drop-fail.rs:44:9 | LL | let mut tmp = None; | ^^^^^^^ constants cannot evaluate destructors diff --git a/src/test/ui/consts/control-flow/drop-fail.rs b/src/test/ui/consts/control-flow/drop-fail.rs index efa5a11c941e9..ed57e1d6e883d 100644 --- a/src/test/ui/consts/control-flow/drop-fail.rs +++ b/src/test/ui/consts/control-flow/drop-fail.rs @@ -8,13 +8,18 @@ const _: Option> = { let x = Some(Vec::new()); //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time - if true { + if unknown() { x } else { y } }; +#[inline(never)] +const fn unknown() -> bool { + true +} + // We only clear `NeedsDrop` if a local is moved from in entirely. This is a shortcoming of the // existing analysis. const _: Vec = { diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr index 72ca4fa08bc4e..a6b7b61177111 100644 --- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr +++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr @@ -8,7 +8,7 @@ LL | }; | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:21:9 + --> $DIR/drop-fail.rs:26:9 | LL | let vec_tuple = (Vec::new(),); | ^^^^^^^^^ constants cannot evaluate destructors @@ -17,7 +17,7 @@ LL | }; | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:29:9 + --> $DIR/drop-fail.rs:34:9 | LL | let x: Result<_, Vec> = Ok(Vec::new()); | ^ constants cannot evaluate destructors @@ -26,7 +26,7 @@ LL | }; | - value is dropped here error[E0493]: destructors cannot be evaluated at compile-time - --> $DIR/drop-fail.rs:39:9 + --> $DIR/drop-fail.rs:44:9 | LL | let mut tmp = None; | ^^^^^^^ constants cannot evaluate destructors