Optimize integral pattern matching
Various improvements to integral pattern matching. Together they reduce instruction counts for `unicode_normalization-check-clean` by about 16%.
r? @Mark-Simulacrum
The `if let Some(val) = value.try_eval_bits(...)` branch in `from_const()` is
very hot for the `unicode_normalization` benchmark.
This commit introduces a special-case alternative for scalars that avoids
`try_eval_bits()` and all the functions it calls (`Const::eval()`,
`ConstValue::try_to_bits()`, `ConstValue::try_to_scalar()`, and
`Scalar::to_bits()`), instead extracting the result immediately.
The type and value checking done by `Scalar::to_bits()` is replicated by moving
it into a new function `Scalar::check_raw()` and using that new function in the
special case.
PR #64673 introduced some special-case handling of scalar types in
`Const::try_eval_bits()`. This handling is now moved out of that function into
the new `IntRange::integral_size_and_signed_bias` function.
This commit reduces the instruction count for
`unicode_normalization-check-clean` by about 10%.
No StableHasherResult everywhere
This removes the generic parameter on `StableHasher`, instead moving it to the call to `finish`. This has the side-effect of making all `HashStable` impls nicer, since we no longer need the verbose `<W: StableHasherResult>` that previously existed -- often forcing line wrapping.
This is done for two reasons:
* we should avoid false "generic" dependency on the result of StableHasher
* we don't need to codegen two/three copies of all the HashStable impls when they're transitively used to produce a fingerprint, u64, or u128. I haven't measured, but this might actually make our artifacts somewhat smaller too.
* Easier to understand/read/write code -- the result of the stable hasher is irrelevant when writing a hash impl.
Add a cycle detector for generic `Graph`s and `mir::Body`s
Cycle detection is one way to differentiate the upcoming `const_loop` feature flag (#52000) from the `const_if_match` one (#49146). It would be possible to use the existing implementation of strongly-connected components for this but less efficient.
The ["tri-color" terminology](http://www.cs.cornell.edu/courses/cs2112/2012sp/lectures/lec24/lec24-12sp.html) is common in introductory data structures and algorithms courses: black nodes are settled, grey nodes are visited, and white nodes have no state. This particular implementation is iterative and uses a well-known technique where "node settled" events are kept on the stack alongside nodes to visit. When a settled event is popped, we know that all successors of that node have been visited and themselves settled. If we encounter a successor node that has been visited (is on the stack) but not yet settled, we have found a cycle.
r? @eddyb
Currently, after a CALL terminator is created in MIR, we insert DROP
statements for all of its operands -- even though they were just moved
shortly before! These spurious drops are later removed, but not before
causing borrow check errors.
This PR series modifies the drop code to track operands that were
moved and avoid creating drops for them.
Right now, I'm only using this mechanism for calls, but it seems
likely it could be used in more places.
Add a `Place::is_indirect` method to determine whether a `Place` contains a `Deref` projection
Working on #63860 requires tracking some property about each local. This requires differentiating `Place`s like `x` and `x.field[index]` from ones like `*x` and `*x.field`, since the first two will always access the same region of memory as `x` while the latter two may access any region of memory. This functionality is duplicated in various places across the compiler. This PR adds a helper method to `Place` which determines whether that `Place` has a `Deref` projection at any point and changes some existing code to use the new method.
I've not converted `qualify_consts.rs` to use the new method, since it's not a trivial conversion and it will get replaced anyway by #63860. There may be other potential uses besides the two I change in this PR.
r? @oli-obk
Value was renamed to Operand in ad2de8b4ee
ScalarPair to Slice in fe50b4eb1d
Not familiar enough with rustc's source to know if the comment is even still applicable.
Make Allocation::bytes private
Fixes#62931.
Direct immutable access to the bytes is still possible but redirected through the new method `raw_bytes_with_undef_and_ptr`, similar to `get_bytes_with_undef_and_ptr` but without requiring an interpretation context and not doing *any* relocation or bounds checks. The `size` of the allocation is stored separately which makes access as `Size` and `usize` more ergonomic.
cc: @RalfJung
This returns whether a `Place` references the same region of memory
as its base, or equivalently whether it contains a `Deref` projection.
This is helpful for analyses that must track state for locals, since an
assignment to `x` or `x.field` is fundamentally different than one to
`*x`, which may mutate any memory region.