rust/compiler
Patrick Walton da630ac79d Introduce deduced parameter attributes, and use them for deducing readonly on
indirect immutable freeze by-value function parameters.

Right now, `rustc` only examines function signatures and the platform ABI when
determining the LLVM attributes to apply to parameters. This results in missed
optimizations, because there are some attributes that can be determined via
analysis of the MIR making up the function body. In particular, `readonly`
could be applied to most indirectly-passed by-value function arguments
(specifically, those that are freeze and are observed not to be mutated), but
it currently is not.

This patch introduces the machinery that allows `rustc` to determine those
attributes. It consists of a query, `deduced_param_attrs`, that, when
evaluated, analyzes the MIR of the function to determine supplementary
attributes. The results of this query for each function are written into the
crate metadata so that the deduced parameter attributes can be applied to
cross-crate functions. In this patch, we simply check the parameter for
mutations to determine whether the `readonly` attribute should be applied to
parameters that are indirect immutable freeze by-value.  More attributes could
conceivably be deduced in the future: `nocapture` and `noalias` come to mind.

Adding `readonly` to indirect function parameters where applicable enables some
potential optimizations in LLVM that are discussed in [issue 103103] and [PR
103070] around avoiding stack-to-stack memory copies that appear in functions
like `core::fmt::Write::write_fmt` and `core::panicking::assert_failed`. These
functions pass a large structure unchanged by value to a subfunction that also
doesn't mutate it. Since the structure in this case is passed as an indirect
parameter, it's a pointer from LLVM's perspective. As a result, the
intermediate copy of the structure that our codegen emits could be optimized
away by LLVM's MemCpyOptimizer if it knew that the pointer is `readonly
nocapture noalias` in both the caller and callee. We already pass `nocapture
noalias`, but we're missing `readonly`, as we can't determine whether a
by-value parameter is mutated by examining the signature in Rust. I didn't have
much success with having LLVM infer the `readonly` attribute, even with fat
LTO; it seems that deducing it at the MIR level is necessary.

No large benefits should be expected from this optimization *now*; LLVM needs
some changes (discussed in [PR 103070]) to more aggressively use the `noalias
nocapture readonly` combination in its alias analysis. I have some LLVM patches
for these optimizations and have had them looked over. With all the patches
applied locally, I enabled LLVM to remove all the `memcpy`s from the following
code:

```rust
fn main() {
    println!("Hello {}", 3);
}
```

which is a significant codegen improvement over the status quo. I expect that
if this optimization kicks in in multiple places even for such a simple
program, then it will apply to Rust code all over the place.

[issue 103103]: https://github.com/rust-lang/rust/issues/103103

[PR 103070]: https://github.com/rust-lang/rust/pull/103070
2022-10-21 02:33:15 -07:00
..
rustc Don't rerun the build script for the compiler each time on linux 2022-07-10 23:57:25 -05:00
rustc_apfloat Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_arena Make use of [wrapping_]byte_{add,sub} 2022-08-23 19:32:37 +04:00
rustc_ast Fix TyKind::is_simple_path. 2022-10-18 15:51:23 +11:00
rustc_ast_lowering Do anonymous lifetimes remapping correctly for nested rpits 2022-10-19 16:49:39 -03:00
rustc_ast_passes Improve "~const is not allowed here" message 2022-10-20 19:32:16 +00:00
rustc_ast_pretty Rename AssocItemKind::TyAlias to AssocItemKind::Type 2022-10-10 02:31:37 +00:00
rustc_attr Remove from compiler/ crates 2022-09-29 16:49:04 +09:00
rustc_borrowck Auto merge of #103290 - matthiaskrgr:rollup-ngozai3, r=matthiaskrgr 2022-10-20 13:33:50 +00:00
rustc_builtin_macros Mark derived StructuralEq as automatically derived. 2022-10-15 15:16:32 +00:00
rustc_codegen_cranelift more dupe word typos 2022-10-14 12:57:56 +08:00
rustc_codegen_gcc Stabilize asm_sym 2022-10-17 22:38:37 +01:00
rustc_codegen_llvm Rollup merge of #103018 - Rageking8:more-dupe-word-typos, r=TaKO8Ki 2022-10-14 16:19:15 +05:30
rustc_codegen_ssa Auto merge of #103092 - petrochenkov:weaklto, r=wesleywiser 2022-10-20 16:20:50 +00:00
rustc_const_eval Rollup merge of #103315 - RalfJung:interpret-switchint-ice, r=bjorn3 2022-10-20 22:42:41 +02:00
rustc_data_structures Auto merge of #103214 - Nilstrieb:set-theory, r=petrochenkov 2022-10-19 13:53:06 +00:00
rustc_driver Clarify run_in_thread_pool_with_globals. 2022-10-19 17:37:48 +11:00
rustc_error_codes fix small word dupe typos 2022-10-13 00:53:46 +08:00
rustc_error_messages Rollup merge of #102454 - chenyukang:fix-102396-missing-parentheses, r=lcnr 2022-10-17 17:15:49 +02:00
rustc_errors UPDATE - Move IntoDiagnosticArg implementations to diagnostic_impls file 2022-10-12 16:55:28 -04:00
rustc_expand Fix the bug of next_point in span 2022-10-18 02:59:38 +08:00
rustc_feature Stabilize asm_sym 2022-10-17 22:38:37 +01:00
rustc_fs_util Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_graphviz Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_hir Use tidy-alphabetical in the compiler 2022-10-12 17:49:10 +05:30
rustc_hir_analysis Auto merge of #102417 - oli-obk:opaque_lifetimes2, r=jackh726 2022-10-20 00:22:17 +00:00
rustc_hir_pretty pretty: fix to print some lifetimes on HIR pretty-print 2022-10-15 23:34:21 +09:00
rustc_incremental Rollup merge of #102829 - compiler-errors:rename-impl-item-kind, r=TaKO8Ki 2022-10-10 00:09:42 +09:00
rustc_index Remove from compiler/ crates 2022-09-29 16:49:04 +09:00
rustc_infer Make ClosureOutlivesRequirement not rely on an unresolved type 2022-10-19 17:10:59 +00:00
rustc_interface Add a comment to Compiler. 2022-10-19 17:37:50 +11:00
rustc_lexer Remove from compiler/ crates 2022-09-29 16:49:04 +09:00
rustc_lint Rollup merge of #102953 - WaffleLapkin:better_docs_for_decorate_param, r=RalfJung 2022-10-16 17:51:31 +02:00
rustc_lint_defs more dupe word typos 2022-10-14 12:57:56 +08:00
rustc_llvm Avoid LLVM-deprecated Optional::hasValue 2022-09-26 16:51:18 -07:00
rustc_log Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_macros Get rid of rustc_query_description! 2022-10-14 22:35:56 +02:00
rustc_metadata Introduce deduced parameter attributes, and use them for deducing readonly on 2022-10-21 02:33:15 -07:00
rustc_middle Introduce deduced parameter attributes, and use them for deducing readonly on 2022-10-21 02:33:15 -07:00
rustc_mir_build Auto merge of #101832 - compiler-errors:dyn-star-plus, r=eholk 2022-10-15 07:36:38 +00:00
rustc_mir_dataflow Rollup merge of #102675 - ouz-a:mir-technical-debt, r=oli-obk 2022-10-08 14:38:18 +02:00
rustc_mir_transform Introduce deduced parameter attributes, and use them for deducing readonly on 2022-10-21 02:33:15 -07:00
rustc_monomorphize mir constants: type traversing bye bye 2022-10-17 10:54:01 +02:00
rustc_parse Fix the bug of next_point in span 2022-10-18 02:59:38 +08:00
rustc_parse_format Detect and reject out-of-range integers in format string literals 2022-10-01 01:05:01 +02:00
rustc_passes Allow #[unstable] impl for fn() -> UnstableType. 2022-10-19 13:34:18 +02:00
rustc_plugin_impl Remove from compiler/ crates 2022-09-29 16:49:04 +09:00
rustc_privacy Auto merge of #102026 - Bryanskiy:resolve_update, r=petrochenkov 2022-10-16 20:34:38 +00:00
rustc_query_impl Introduce deduced parameter attributes, and use them for deducing readonly on 2022-10-21 02:33:15 -07:00
rustc_query_system Remove the describe method from the QueryDescription trait 2022-10-14 22:35:56 +02:00
rustc_resolve Rollup merge of #103221 - TaKO8Ki:fix-103202, r=oli-obk 2022-10-20 22:42:38 +02:00
rustc_save_analysis ImplItemKind::TyAlias => ImplItemKind::Type 2022-10-09 07:09:57 +00:00
rustc_serialize remove cfg(bootstrap) 2022-09-26 10:14:45 +02:00
rustc_session Remove RunCompiler::emitter. 2022-10-18 08:48:58 +11:00
rustc_smir Only keep one version of ImplicitSelfKind. 2022-09-13 19:18:23 +02:00
rustc_span Auto merge of #103185 - chenyukang:yukang/fix-span-next-point, r=davidtwco 2022-10-20 10:40:09 +00:00
rustc_symbol_mangling more dupe word typos 2022-10-14 12:57:56 +08:00
rustc_target Split is_stable from rustc_target::spec::abi::is_enabled. 2022-10-19 12:41:11 +02:00
rustc_trait_selection Don't call own_existential_vtable_entries on unresolved trait ref 2022-10-19 17:11:40 +00:00
rustc_traits rm try_normalize_mir_const_after_erasing_regions 2022-10-17 10:54:03 +02:00
rustc_transmute Remove TypeckResults from InferCtxt 2022-10-07 07:06:19 -05:00
rustc_ty_utils Introduce deduced parameter attributes, and use them for deducing readonly on 2022-10-21 02:33:15 -07:00
rustc_type_ir Deny const variables as well 2022-10-19 17:11:40 +00:00