You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
rustc_codegen_ssa: Use llvm.invariant intrinsics on arguments that are
immutable references; off by default.
Optimization failures around reloads and memcpy optimizations are frequently
traceable to LLVM's failure to prove that memory can't be mutated by a call or
store. This problem is especially acute in Rust, where large values tend to be
memcpy'd more often than in C++. Thankfully, Rust has stronger guarantees on
mutability available than C++ does, via the strong immutability of `&`
references. This should allow LLVM to prove that memory can't be modified by
stores and calls in more cases.
We're already using LLVM's `readonly` parameter attribute on such calls.
However, the semantics of `readonly` are akin to `const` in C++, in that they
only promise to LLVM that the function won't mutate the parameter *through that
pointer*, not that the pointed-to memory is immutable for the entire duration
of the function. These weak semantics limit the applicability of `readonly` to
LLVM's alias analysis. Instead of `readonly`, the correct way to express strong
immutability guarantees on memory is through the `llvm.invariant.start` and
`llvm.invariant.end` intrinsics. These enable a frontend like `rustc` to
describe immutability of memory regions in an expressive, flow-sensitive
manner.
Unfortunately, LLVM doesn't use the `llvm.invariant.start` and
`llvm.invariant.end` intrinsics for much at the moment. It's only used in one
optimization in loop-invariant code motion at this time. Follow-up work will
need to be done in LLVM to integrate these intrinsics into alias analysis.
Possibly there will need to be some sort of "MemoryInvarianceAnalysis" that
uses graph reachability algorithms to analyze the extent of the guarantees
provided by these intrinsics to the control flow graph.
Regardless, this front-end work needs to happen as a prerequisite for any LLVM
work, so that the improvements to LLVM can be measured and tested. So this
commit makes `rustc` use `llvm.invariant` in a minimal way: on immutable
references to "freeze" types (i.e. not transitively containing UnsafeCell)
passed directly as parameters to functions. This is off by default, gated
behind the non-default `-Z emit-invariant-markers=yes` flag.
Obviously, a lot more can be done to use `llvm.invariant` more liberally in the
future, but this can be added over time, especially once more LLVM optimization
passes use that infrastructure. This is simply the bare minimum for now. Once
LLVM uses those intrinsics for more optimizations, the effects of more
`llvm.invariant` use can be measured more precisely.
Copy file name to clipboardExpand all lines: src/test/rustdoc-ui/z-help.stdout
+1
Original file line number
Diff line number
Diff line change
@@ -36,6 +36,7 @@
36
36
-Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
37
37
-Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
38
38
-Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
39
+
-Z emit-invariant-markers=val -- emit `llvm.invariant` markers, which may enable better optimization (default: no)
0 commit comments