Auto merge of #28651 - dotdash:exhaustive_match, r=eddyb
By putting an "unreachable" instruction into the default arm of a switch instruction we can let LLVM know that the match is exhaustive, allowing for better optimizations. For example, this match: ```rust pub enum Enum { One, Two, Three, } impl Enum { pub fn get_disc(self) -> u8 { match self { Enum::One => 0, Enum::Two => 1, Enum::Three => 2, } } } ``` Currently compiles to this on x86_64: ```asm .cfi_startproc movzbl %dil, %ecx cmpl $1, %ecx setne %al testb %cl, %cl je .LBB0_2 incb %al movb %al, %dil .LBB0_2: movb %dil, %al retq .Lfunc_end0: ``` But with this change we get: ```asm .cfi_startproc movb %dil, %al retq .Lfunc_end0: ```
This commit is contained in:
commit
dde7283b80
@ -1283,6 +1283,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
let exhaustive = chk.is_infallible() && defaults.is_empty();
|
||||
let len = opts.len();
|
||||
|
||||
if exhaustive && kind == Switch {
|
||||
build::Unreachable(else_cx);
|
||||
}
|
||||
|
||||
// Compile subtrees for each option
|
||||
for (i, opt) in opts.iter().enumerate() {
|
||||
// In some cases of range and vector pattern matching, we need to
|
||||
@ -1293,7 +1297,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
let mut opt_cx = else_cx;
|
||||
let debug_loc = opt.debug_loc();
|
||||
|
||||
if !exhaustive || i + 1 < len {
|
||||
if kind == Switch || !exhaustive || i + 1 < len {
|
||||
opt_cx = bcx.fcx.new_temp_block("match_case");
|
||||
match kind {
|
||||
Single => Br(bcx, opt_cx.llbb, debug_loc),
|
||||
|
30
src/test/codegen/match.rs
Normal file
30
src/test/codegen/match.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub enum E {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @exhaustive_match
|
||||
#[no_mangle]
|
||||
pub fn exhaustive_match(e: E) {
|
||||
// CHECK: switch{{.*}}, label %[[DEFAULT:[a-zA-Z0-9_]+]]
|
||||
// CHECK: [[DEFAULT]]:
|
||||
// CHECK-NEXT: unreachable
|
||||
match e {
|
||||
E::A => (),
|
||||
E::B => (),
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user