Move the libgccjit.so file in a target directory
Since GCC is not multi-target, we need multiple libgccjit.so. Our solution to have a directory per target so that we can have multiple libgccjit.so.
r? `@Kobzol`
Compute jump threading opportunities in a single pass
The current implementation of jump threading walks MIR CFG backwards from each `SwitchInt` terminator. This PR replaces this by a single postorder traversal of MIR. In theory, we could do a full fixpoint dataflow analysis, but this has low returns as we forbid threading through a loop header.
The second commit in this PR modifies the carried state to a lighter data structure. The current implementation uses some kind of `IndexVec<ValueIndex, &[Condition]>`. This is needlessly heavy, as the state rarely ever carries more than a few `Condition`s. The first commit replaces this state with a simpler `&[Condition]`, and puts the corresponding `ValueIndex` inside `Condition`.
The three later commits are perf tweaks.
The sixth commit is the main change. Instead of carrying the goto target inside the condition, we maintain a set of conditions associated with each block, and their consequences in following blocks. Think: if this condition is fulfilled in this block, then that condition is fulfilled in that block. This makes the threading algorithm much easier to implement, without the extra bookkeeping of `ThreadingOpportunity` we had.
Later commits modify that algorithm to shrink the set of duplicated blocks. By propagating fulfilled conditions down the CFG, and trimming costly threads.
Fix MaybeUninit codegen using GVN
This is an alternative to https://github.com/rust-lang/rust/pull/142837, based on https://github.com/rust-lang/rust/pull/146355#discussion_r2421651968.
The general approach I took here is to aggressively propagate anything that is entirely uninitialized. GVN generally takes the approach of only synthesizing small types, but we need to generate large consts to fix the codegen issue.
I also added a special case to MIR dumps for this where now an entirely uninit const is printed as `const <uninit>`, because otherwise we end up with extremely verbose dumps of the new consts.
After GVN though, we still end up with a lot of MIR that looks like this:
```
StorageLive(_1);
_1 = const <uninit>;
_2 = &raw mut _1;
```
Which will break tests/codegen-llvm/maybeuninit-rvo.rs with the naive lowering. I think the ideal fix here is to somehow omit these `_1 = const <uninit>` assignments that come directly after a StorageLive, but I'm not sure how to do that. For now at least, ignoring such assignments (even if they don't come right after a StorageLive) in codegen seems to work.
Note that since GVN is based on synthesizing a `ConstValue` which has a defined layout, this scenario still gets deoptimized by LLVM.
```rust
#![feature(rustc_attrs)]
#![crate_type = "lib"]
use std::mem::MaybeUninit;
#[unsafe(no_mangle)]
pub fn oof() -> [[MaybeUninit<u8>; 8]; 8] {
#[rustc_no_mir_inline]
pub fn inner<T: Copy>() -> [[MaybeUninit<T>; 8]; 8] {
[[MaybeUninit::uninit(); 8]; 8]
}
inner()
}
```
This case can be handled correctly if enough inlining has happened, or it could be handled by post-mono GVN. Synthesizing `UnevaluatedConst` or some other special kind of const seems dubious.
Previously copy propagation presumed that there is further unspecified
distinction between move operands and copy operands in assignments and
propagated moves from assignments into terminators. This is inconsistent
with current operational semantics.
Turn moves into copies after copy propagation to preserve existing behavior.
Fixes https://github.com/rust-lang/rust/issues/137936.
Fixes https://github.com/rust-lang/rust/issues/146423.
Fix tests for big-endian
The tests fail on s390x and presumably other big-endian systems, due to check of raw alloc values in the MIR output.
To fix the tests remove the raw bytes from the MIR output (via: compile-flags: -Zdump-mir-exclude-alloc-bytes) and update the matching diffs.
Add FileCheck annotations to mir-opt/copy-prop
This resolves a part of https://github.com/rust-lang/rust/issues/116971 .
This PR adds FileCheck annotations to test files under mir-opt/copy-prop.
Do not lifetime-extend array/slice indices
When lowering non-overloaded indexing operations to MIR, this uses the temporary lifetime of the index expression for the index temporary, rather than applying the temporary lifetime of the indexing operation as a whole to the index.
For example, in
```rust
let x = &xs[i];
```
previously, the temporary containing the result of evaluating `i` would live until the end of the block due to the indexing operation being [lifetime-extended](https://doc.rust-lang.org/nightly/reference/destructors.html#temporary-lifetime-extension). Under this PR, the index temporary only lives to the end of the `let` statement because it uses the more precise temporary lifetime of the index expression.
I don't think this will affect semantics in an observable way, but the more precise `StorageDead` placement may slightly improve analysis/codegen performance.
r? mir
The tests fail on s390x and presumably other big-endian systems, due
to check of raw alloc values in the MIR output.
To fix the tests remove the raw bytes from the MIR output
(via: compile-flags: -Zdump-mir-exclude-alloc-bytes) and update the
matching diffs.