rust/compiler
bors 50dff955a9 Auto merge of #106285 - cjgillot:refprop-ssa, r=JakobDegen
Implement SSA-based reference propagation

Rust has a tendency to create a lot of short-lived borrows, in particular for method calls. This PR aims to remove those short-lived borrows with a const-propagation dedicated to pointers to local places.

This pass aims to transform the following pattern:
```
  _1 = &raw? mut? PLACE;
  _3 = *_1;
  _4 = &raw? mut? *_1;
```

Into
```
  _1 = &raw? mut? PLACE;
  _3 = PLACE;
  _4 = &raw? mut? PLACE;
```

where `PLACE` is a direct or an indirect place expression.

By removing indirection, this pass should help both dest-prop and const-prop to handle more cases.
This optimization is distinct from const-prop and dataflow const-prop since the borrow-reborrow patterns needs to preserve borrowck invariants, especially the uniqueness property of mutable references.

The pointed-to places are computed using a SSA analysis. We suppose that removable borrows are typically temporaries from autoref, so they are by construction assigned only once, and a SSA analysis is enough to catch them. For each local, we store both where and how it is used, in order to efficiently compute the all-or-nothing property. Thanks to `Derefer`, we only have to track locals, not places in general.

---

There are 3 properties that need to be upheld for this transformation to be legal:
- place constness: `PLACE` must refer to the same memory wherever it appears;
- pointer liveness: we must not introduce dereferences of dangling pointers;
- `&mut` borrow uniqueness.

## Constness

If `PLACE` is an indirect projection, if its of the form `(*LOCAL).PROJECTIONS` where:
- `LOCAL` is SSA;
- all projections in `PROJECTIONS` are constant (no dereference and no indexing).

If `PLACE` is a direct projection of a local, we consider it as constant if:
- the local is always live, or it has a single `StorageLive` that dominates all uses;
- all projections are constant.

# Liveness

When performing a substitution, we must take care not to introduce uses of dangling locals.

Using a dangling borrow is UB. Therefore, we assume that for any use of `*x`, where `x` is a borrow, the pointed-to memory is live.

Limitations:
- occurrences of `*x` in an `&raw mut? *x` are accepted;
- raw pointers are allowed to be dangling.

In those 2 case, we do not substitute anything, to be on the safe side.

**Open question:** we do not differentiate borrows of ZST and non-ZST. The UB rules may be
different depending on the layout. Having a different treatment would effectively prevent this
pass from running on polymorphic MIR, which defeats the purpose of MIR opts.

## Uniqueness

For `&mut` borrows, we also need to preserve the uniqueness property:
we must avoid creating a state where we interleave uses of `*_1` and `_2`.
To do it, we only perform full substitution of mutable borrows:
we replace either all or none of the occurrences of `*_1`.

Some care has to be taken when `_1` is copied in other locals.
```
   _1 = &raw? mut? _2;
   _3 = *_1;
   _4 = _1
   _5 = *_4
```
In such cases, fully substituting `_1` means fully substituting all of the copies.

For immutable borrows, we do not need to preserve such uniqueness property,
so we perform all the possible substitutions without removing the `_1 = &_2` statement.
2023-05-09 21:54:34 +00:00
..
rustc
rustc_abi
rustc_apfloat
rustc_arena
rustc_ast Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=cjgillot 2023-05-09 20:49:32 +02:00
rustc_ast_lowering Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=cjgillot 2023-05-09 20:49:32 +02:00
rustc_ast_passes
rustc_ast_pretty
rustc_attr
rustc_baked_icu_data
rustc_borrowck Rollup merge of #110583 - Ezrashaw:tweak-make-mut-spans, r=estebank 2023-05-09 12:33:45 +05:30
rustc_builtin_macros Rollup merge of #110694 - est31:builtin, r=petrochenkov 2023-05-09 12:33:45 +05:30
rustc_codegen_cranelift
rustc_codegen_gcc
rustc_codegen_llvm Rollup merge of #104070 - nbdd0121:unwind, r=Amanieu 2023-05-08 09:30:21 -07:00
rustc_codegen_ssa Rollup merge of #110304 - cchiw:master, r=davidtwco 2023-05-09 12:33:44 +05:30
rustc_const_eval
rustc_data_structures Rollup merge of #111252 - matthewjasper:min-spec-improvements, r=compiler-errors 2023-05-09 12:33:46 +05:30
rustc_driver
rustc_driver_impl Rollup merge of #111004 - clubby789:migrate-mir-transform, r=oli-obk 2023-05-08 09:30:22 -07:00
rustc_error_codes Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=cjgillot 2023-05-09 20:49:32 +02:00
rustc_error_messages
rustc_errors Rollup merge of #111004 - clubby789:migrate-mir-transform, r=oli-obk 2023-05-08 09:30:22 -07:00
rustc_expand
rustc_feature Rollup merge of #110694 - est31:builtin, r=petrochenkov 2023-05-09 12:33:45 +05:30
rustc_fluent_macro
rustc_fs_util
rustc_graphviz
rustc_hir
rustc_hir_analysis Rollup merge of #111215 - BoxyUwU:resolve_anon_consts_differently, r=cjgillot 2023-05-09 20:49:32 +02:00
rustc_hir_pretty
rustc_hir_typeck Rollup merge of #110504 - compiler-errors:tweak-borrow-sugg, r=cjgillot 2023-05-09 12:33:44 +05:30
rustc_incremental
rustc_index
rustc_infer Rollup merge of #109410 - fmease:iat-alias-kind-inherent, r=compiler-errors 2023-05-08 09:30:21 -07:00
rustc_interface
rustc_lexer
rustc_lint Rollup merge of #109410 - fmease:iat-alias-kind-inherent, r=compiler-errors 2023-05-08 09:30:21 -07:00
rustc_lint_defs Auto merge of #106621 - ozkanonur:enable-elided-lifetimes-for-doctests, r=Mark-Simulacrum 2023-05-08 04:50:28 +00:00
rustc_llvm
rustc_log
rustc_macros Rollup merge of #111120 - chenyukang:yukang-suggest-let, r=Nilstrieb 2023-05-09 12:33:46 +05:30
rustc_metadata
rustc_middle Auto merge of #106285 - cjgillot:refprop-ssa, r=JakobDegen 2023-05-09 21:54:34 +00:00
rustc_mir_build
rustc_mir_dataflow Explicitly skip arguments. 2023-05-09 17:59:35 +00:00
rustc_mir_transform Correct StorageLive comment. 2023-05-09 17:59:35 +00:00
rustc_monomorphize
rustc_parse Rollup merge of #111120 - chenyukang:yukang-suggest-let, r=Nilstrieb 2023-05-09 12:33:46 +05:30
rustc_parse_format
rustc_passes
rustc_plugin_impl
rustc_privacy Auto merge of #111371 - compiler-errors:revert-110907, r=petrochenkov 2023-05-09 15:16:17 +00:00
rustc_query_impl
rustc_query_system
rustc_resolve Revert "Populate effective visibilities in rustc_privacy" 2023-05-08 21:47:44 +00:00
rustc_serialize
rustc_session Rollup merge of #105354 - BlackHoleFox:apple-deployment-printer, r=oli-obk 2023-05-08 19:41:48 +09:00
rustc_smir
rustc_span Limit lifetime of format_args!() with inlined args. 2023-05-09 16:08:40 +02:00
rustc_symbol_mangling
rustc_target Rollup merge of #111332 - loongarch-rs:inline-asm, r=Amanieu 2023-05-08 19:41:51 +09:00
rustc_trait_selection Rollup merge of #111252 - matthewjasper:min-spec-improvements, r=compiler-errors 2023-05-09 12:33:46 +05:30
rustc_traits
rustc_transmute
rustc_ty_utils Fix miscompilation when adding default method to Future 2023-05-08 17:06:48 +02:00
rustc_type_ir