Skip to content

Commit 9cc67c5

Browse files
committed
Lower assume(false) to an unreachable terminator
1 parent 766bdce commit 9cc67c5

File tree

3 files changed

+52
-5
lines changed

3 files changed

+52
-5
lines changed

compiler/rustc_codegen_ssa/src/mir/block.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc_target::abi::{self, HasDataLayout, WrappingRange};
2323
use rustc_target::spec::abi::Abi;
2424

2525
use std::cmp;
26+
use std::ops::ControlFlow;
2627

2728
// Indicates if we are in the middle of merging a BB's successor into it. This
2829
// can happen when BB jumps directly to its successor and the successor has no
@@ -1213,13 +1214,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12131214

12141215
debug!("codegen_block({:?}={:?})", bb, data);
12151216

1217+
let mut replaced_terminator = false;
12161218
for statement in &data.statements {
1217-
self.codegen_statement(bx, statement);
1219+
if let ControlFlow::Break(()) = self.codegen_statement(bx, statement) {
1220+
replaced_terminator = true;
1221+
break;
1222+
}
12181223
}
12191224

1220-
let merging_succ = self.codegen_terminator(bx, bb, data.terminator());
1221-
if let MergingSucc::False = merging_succ {
1225+
if replaced_terminator {
12221226
break;
1227+
} else {
1228+
let merging_succ = self.codegen_terminator(bx, bb, data.terminator());
1229+
if let MergingSucc::False = merging_succ {
1230+
break;
1231+
}
12231232
}
12241233

12251234
// We are merging the successor into the produced backend basic

compiler/rustc_codegen_ssa/src/mir/statement.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ use super::FunctionCx;
66
use super::LocalRef;
77
use crate::traits::*;
88

9+
use std::ops::ControlFlow;
10+
911
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1012
#[instrument(level = "debug", skip(self, bx))]
11-
pub fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx>) {
13+
pub fn codegen_statement(
14+
&mut self,
15+
bx: &mut Bx,
16+
statement: &mir::Statement<'tcx>,
17+
) -> ControlFlow<()> {
1218
self.set_debug_loc(bx, statement.source_info);
1319
match statement.kind {
1420
mir::StatementKind::Assign(box (ref place, ref rvalue)) => {
@@ -70,7 +76,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
7076
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
7177
if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) {
7278
let op_val = self.codegen_operand(bx, op);
73-
bx.assume(op_val.immediate());
79+
let imm = op_val.immediate();
80+
if let Some(value) = bx.const_to_opt_uint(imm) {
81+
if value == 0 {
82+
bx.unreachable();
83+
return ControlFlow::Break(());
84+
}
85+
} else {
86+
bx.assume(imm);
87+
}
7488
}
7589
}
7690
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
@@ -97,5 +111,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
97111
| mir::StatementKind::PlaceMention(..)
98112
| mir::StatementKind::Nop => {}
99113
}
114+
ControlFlow::Continue(())
100115
}
101116
}

tests/codegen/discriminant-swap.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ compile-flags: -O
2+
3+
#![crate_type = "lib"]
4+
5+
use std::hint::unreachable_unchecked;
6+
use std::ptr::{read, write};
7+
8+
type T = [u8; 753];
9+
10+
pub enum State {
11+
A(T),
12+
B(T),
13+
}
14+
15+
// CHECK-LABEL: @init(ptr {{.*}}s)
16+
// CHECK-NEXT: start
17+
// CHECK-NEXT: store i8 1, ptr %s, align 1
18+
// CHECK-NEXT: ret void
19+
#[no_mangle]
20+
unsafe fn init(s: *mut State) {
21+
let State::A(v) = read(s) else { unreachable_unchecked() };
22+
write(s, State::B(v));
23+
}

0 commit comments

Comments
 (0)