Auto merge of #124188 - scottmcm:implicit-switchint-unreachable, r= · rust-lang/rust@5ed2b42 (original) (raw)
`@@ -5,7 +5,8 @@ use rustc_ast as ast;
`
5
5
`use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
`
6
6
`use rustc_hir::lang_items::LangItem;
`
7
7
`use rustc_middle::mir::{
`
8
``
`-
self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason,
`
``
8
`+
self, AssertKind, BasicBlock, InlineAsmMacro, SwitchAction, SwitchTargets,
`
``
9
`+
UnwindTerminateReason,
`
9
10
`};
`
10
11
`use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
`
11
12
`use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
`
`@@ -96,6 +97,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
`
96
97
`}
`
97
98
`}
`
98
99
``
``
100
`+
fn llbb_with_cleanup_from_switch_action<Bx: BuilderMethods<'a, 'tcx>>(
`
``
101
`+
&self,
`
``
102
`+
fx: &mut FunctionCx<'a, 'tcx, Bx>,
`
``
103
`+
target: mir::SwitchAction,
`
``
104
`+
) -> Bx::BasicBlock {
`
``
105
`+
match target {
`
``
106
`+
mir::SwitchAction::Unreachable => fx.unreachable_block(),
`
``
107
`+
mir::SwitchAction::Goto(bb) => self.llbb_with_cleanup(fx, bb),
`
``
108
`+
}
`
``
109
`+
}
`
``
110
+
99
111
`fn llbb_characteristics<Bx: BuilderMethods<'a, 'tcx>>(
`
100
112
`&self,
`
101
113
`fx: &mut FunctionCx<'a, 'tcx, Bx>,
`
`@@ -368,7 +380,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
368
380
`// If our discriminant is a constant we can branch directly
`
369
381
`if let Some(const_discr) = bx.const_to_opt_u128(discr_value, false) {
`
370
382
`let target = targets.target_for_value(const_discr);
`
371
``
`-
bx.br(helper.llbb_with_cleanup(self, target));
`
``
383
`+
bx.br(helper.llbb_with_cleanup_from_switch_action(self, target));
`
372
384
`return;
`
373
385
`};
`
374
386
``
`@@ -379,9 +391,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
379
391
`let (test_value, target) = target_iter.next().unwrap();
`
380
392
`let otherwise = targets.otherwise();
`
381
393
`let lltarget = helper.llbb_with_cleanup(self, target);
`
382
``
`-
let llotherwise = helper.llbb_with_cleanup(self, otherwise);
`
``
394
`+
let llotherwise = helper.llbb_with_cleanup_from_switch_action(self, otherwise);
`
383
395
`let target_cold = self.cold_blocks[target];
`
384
``
`-
let otherwise_cold = self.cold_blocks[otherwise];
`
``
396
`+
let otherwise_cold = match otherwise {
`
``
397
`+
SwitchAction::Goto(otherwise) => self.cold_blocks[otherwise],
`
``
398
`+
SwitchAction::Unreachable => true,
`
``
399
`+
};
`
385
400
`` // If target_cold == otherwise_cold
, the branches have the same weight
``
386
401
`` // so there is no expectation. If they differ, the target
branch is expected
``
387
402
`` // when the otherwise
branch is cold.
``
`@@ -406,7 +421,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
406
421
`}
`
407
422
`} else if self.cx.sess().opts.optimize == OptLevel::No
`
408
423
` && target_iter.len() == 2
`
409
``
`-
&& self.mir[targets.otherwise()].is_empty_unreachable()
`
``
424
`+
&& self.mir.basic_blocks.is_empty_unreachable(targets.otherwise())
`
410
425
`{
`
411
426
`` // In unoptimized builds, if there are two normal targets and the otherwise
target is
``
412
427
`` // an unreachable BB, emit br
instead of switch
. This leaves behind the unreachable
``
`@@ -431,7 +446,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
431
446
`} else {
`
432
447
` bx.switch(
`
433
448
` discr_value,
`
434
``
`-
helper.llbb_with_cleanup(self, targets.otherwise()),
`
``
449
`+
helper.llbb_with_cleanup_from_switch_action(self, targets.otherwise()),
`
435
450
` target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
`
436
451
`);
`
437
452
`}
`
`@@ -1648,11 +1663,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
1648
1663
`}
`
1649
1664
``
1650
1665
`fn unreachable_block(&mut self) -> Bx::BasicBlock {
`
1651
``
`-
self.unreachable_block.unwrap_or_else(|| {
`
``
1666
`+
*self.unreachable_block.get_or_insert_with(|| {
`
1652
1667
`let llbb = Bx::append_block(self.cx, self.llfn, "unreachable");
`
1653
1668
`let mut bx = Bx::build(self.cx, llbb);
`
1654
1669
` bx.unreachable();
`
1655
``
`-
self.unreachable_block = Some(llbb);
`
1656
1670
` llbb
`
1657
1671
`})
`
1658
1672
`}
`