about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-10-31 00:40:32 +0000
committerbors <bors@rust-lang.org>2022-10-31 00:40:32 +0000
commitd726c8467c06088d5d4488edf6b015ec9698c1ea (patch)
tree1df090647efa2e06275cc8060df4774f9affdea7 /compiler/rustc_codegen_llvm/src
parent77e57db384aca99444c3b5f6a9c86bc58a804d89 (diff)
parent003a3f8cd3ea4594e2c2bc89c05562a202868ce0 (diff)
downloadrust-d726c8467c06088d5d4488edf6b015ec9698c1ea.tar.gz
rust-d726c8467c06088d5d4488edf6b015ec9698c1ea.zip
Auto merge of #103331 - nnethercote:convert-switch-to-br, r=scottmcm
Use `br` instead of `switch` in more cases.

`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).

r? `@scottmcm`
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
0 files changed, 0 insertions, 0 deletions