about summary refs log tree commit diff
path: root/src/test/codegen/match.rs
AgeCommit message (Collapse)AuthorLines
2022-10-31Use `br` instead of `switch` in more cases.Nicholas Nethercote-29/+0
`codegen_switchint_terminator` already uses `br` instead of `switch` when there is one normal target plus the `otherwise` target. But there's another common case with two normal targets and an `otherwise` target that points to an empty unreachable BB. This comes up a lot when switching on the tags of enums that use niches. The pattern looks like this: ``` bb1: ; preds = %bb6 %3 = load i8, ptr %_2, align 1, !range !9, !noundef !4 %4 = sub i8 %3, 2 %5 = icmp eq i8 %4, 0 %_6 = select i1 %5, i64 0, i64 1 switch i64 %_6, label %bb3 [ i64 0, label %bb4 i64 1, label %bb2 ] bb3: ; preds = %bb1 unreachable ``` This commit adds code to convert the `switch` to a `br`: ``` bb1: ; preds = %bb6 %3 = load i8, ptr %_2, align 1, !range !9, !noundef !4 %4 = sub i8 %3, 2 %5 = icmp eq i8 %4, 0 %_6 = select i1 %5, i64 0, i64 1 %6 = icmp eq i64 %_6, 0 br i1 %6, label %bb4, label %bb2 bb3: ; No predecessors! unreachable ``` This has a surprisingly large effect on compile times, with reductions of 5% on debug builds of some crates. The reduction is all due to LLVM taking less time. Maybe LLVM is just much better at handling `br` than `switch`. The resulting code is still suboptimal. - The `icmp`, `select`, `icmp` sequence is silly, converting an `i1` to an `i64` and back to an `i1`. But with the current code structure it's hard to avoid, and LLVM will easily clean it up, in opt builds at least. - `bb3` is usually now truly dead code (though not always, so it can't be removed universally).
2022-05-25Update some codegen tests for opaque pointersNikita Popov-2/+2
2021-05-17rustc_codegen_ssa: only create backend `BasicBlock`s as-needed.Eduard-Mihai Burtescu-3/+3
2019-11-21Introduce MIR optimizations for simplifying `x?` on `Result`s.Mazdak Farrokhzad-3/+5
This optimization depends on inlining for the identity conversions introduced by the lowering of the `?`. To take advantage of `SimplifyArmIdentity`, `-Z mir-opt-level=2` is required because that triggers the inlining MIR optimization.
2019-06-13Create fewer basic blocks in match MIR loweringMatthew Jasper-2/+2
2019-02-21Fix codegen testMatthew Jasper-2/+2
2018-12-25Remove licensesMark Rousskov-10/+0
2018-02-20rustc_mir: always run the deaggregator.Eduard-Mihai Burtescu-3/+3
2017-11-14always add an unreachable branch on matches to give more info to llvm about ↵Djzin-3/+6
which values are possible
2017-02-10Rebase fixupsSimonas Kazlauskas-1/+1
2017-02-10Fix codegen testSimonas Kazlauskas-3/+7
2015-09-25Tell LLVM when a match is exhaustiveBjörn Steinbrink-0/+30
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: ```