[MIR] Deaggregate structs to enable further optimizations
Currently, we generate MIR like:
```
tmp0 = ...;
tmp1 = ...;
tmp3 = Foo { a: ..., b: ... };
```
This PR implements "deaggregation," i.e.:
```
tmp3.0 = ...
tmp3.1 = ...
```
Currently, the code only deaggregates structs, not enums. My understanding is that we do not have MIR to set the discriminant of an enum.
Add MIR Optimization Tests
I've starting working on the infrastructure for testing MIR optimizations.
The plan now is to have a set of test cases (written in Rust), compile them with -Z dump-mir, and check the MIR before and after each pass.
Previously we would rebuild all drops on every early exit from a scope, which for code like:
```rust
match x {
a => return 1,
b => return 2,
...
z => return 27
}
```
would produce 27 exactly same chains of drops for each return, a O(n*m) explosion in drops.
Use it instead of a `panic` for inexhaustive matches and correct the
comment. I think we trust our match-generation algorithm enough to
generate these blocks, and not generating an `unreachable` means that
LLVM won't optimize `match void() {}` to an `unreachable`.
[MIR] Implement overflow checking
The initial set of changes is from @Aatch's #33255 PR, rebased on master, plus:
Added an `Assert` terminator to MIR, to simplify working with overflow and bounds checks.
With this terminator, error cases can be accounted for directly, instead of looking for lang item calls.
It also keeps the MIR slimmer, with no extra explicit blocks for the actual panic calls.
Warnings can be produced when the `Assert` is known to always panic at runtime, e.g.:
```rust
warning: index out of bounds: the len is 1 but the index is 3
--> <anon>:1:14
1 |> fn main() { &[std::io::stdout()][3]; }
|> ^^^^^^^^^^^^^^^^^^^^^^
```
Generalized the `OperandValue::FatPtr` optimization to any aggregate pair of immediates.
This allows us to generate the same IR for overflow checks as old trans, not something worse.
For example, addition on `i16` calls `llvm.sadd.with.overflow.i16`, which returns `{i16, i1}`.
However, the Rust type `(i16, bool)`, has to be `{i16, i8}`, only an immediate `bool` is `i1`.
But if we split the pair into an `i16` and an `i1`, we can pass them around as such for free.
The latest addition is a rebase of #34054, updated to work for pairs too. Closes#34054, fixes#33873.
Last but not least, the `#[rustc_inherit_overflow_checks]` attribute was introduced to control the
overflow checking behavior of generic or `#[inline]` functions, when translated in another crate.
It is **not** intended to be used by crates other than `libcore`, which is in the unusual position of
being distributed as only an optimized build with no checks, even when used from debug mode.
Before MIR-based translation, this worked out fine, as the decision for overflow was made at
translation time, in the crate being compiled, but MIR stored in `rlib` has to contain the checks.
To avoid always generating the checks and slowing everything down, a decision was made to
use an attribute in the few spots of `libcore` that need it (see #33255 for previous discussion):
* `core::ops::{Add, Sub, Mul, Neg, Shl, Shr}` implementations for integers, which have `#[inline]` methods and can be used in generic abstractions from other crates
* `core::ops::{Add, Sub, Mul, Neg, Shl, Shr}Assign` same as above, for augmented assignment
* `pow` and `abs` methods on integers, which intentionally piggy-back on built-in multiplication and negation, respectively, to get overflow checks
* `core::iter::{Iterator, Chain, Peek}::count` and `core::iter::Enumerate::{next, nth}`, also documented as panicking on overflow, from addition, counting elements of an iterator in an `usize`
generate fewer basic blocks for variant switches
CC #33567
Adds a new field to TestKind::Switch that tracks the variants that are actually matched against. The other candidates target a common "otherwise" block.