Commit graph

1018 commits

Author SHA1 Message Date
Lukas Markeffsky
c1da4f1d3c fix ensure_monomorphic_enough 2025-02-11 01:15:08 +01:00
Lukas Markeffsky
4898753d5d add test for const type_id misoptimization 2025-02-11 01:10:05 +01:00
bors
4b293d9927 Auto merge of #135701 - calebzulawski:sync-from-portable-simd-2025-01-18, r=workingjubilee
Portable SIMD subtree update

r? `@workingjubilee`
2025-02-10 15:19:51 +00:00
Jubilee
7f8108afc8
Rollup merge of #136053 - Zalathar:defer-counters, r=saethlin
coverage: Defer part of counter-creation until codegen

Follow-up to #135481 and #135873.

One of the pleasant properties of the new counter-assignment algorithm is that we can stop partway through the process, store the intermediate state in MIR, and then resume the rest of the algorithm during codegen. This lets it take into account which parts of the control-flow graph were eliminated by MIR opts, resulting in fewer physical counters and simpler counter expressions.

Those improvements end up completely obsoleting much larger chunks of code that were previously responsible for cleaning up the coverage metadata after MIR opts, while also doing a more thorough cleanup job.

(That change also unlocks some further simplifications that I've kept out of this PR to limit its scope.)
2025-02-10 00:51:49 -08:00
bors
550e035a59 Auto merge of #136450 - compiler-errors:simplify-cast, r=saethlin
Don't reset cast kind without also updating the operand in `simplify_cast` in GVN

Consider this heavily elided segment of the pre-GVN example code that was committed as a test:

```rust
          let _4: *const ();
          let _5: *const [()];
          let mut _6: *const ();
          let _7: *mut ();
          let mut _8: *const [()];
          let mut _9: std::boxed::Box<()>;
          let mut _10: *const ();
          /* ... */
          // Deref a box
          _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
          _4 = copy _10;
          _6 = copy _4;
          // Inlined body of `slice::from_raw_parts`, to turn a unit pointer into a slice-of-unit pointer
          _5 = *const [()] from (copy _6, copy _11);
          _8 = copy _5;
          // Cast the raw slice-of-unit pointer back to a unit pointer
          _7 = copy _8 as *mut () (PtrToPtr);
```

A malformed optimization was changing `_7` (which casted the slice-of-unit ptr to a unit ptr) to:

```
          _7 = copy _5 as *mut () (Transmute);
```

...where `_8` was just replaced with `_5` bc of simple copy propagation, that part is not important... the CastKind changing to Transmute is the important part here.

In #133324, two new functionalities were implemented:
* Peeking through unsized -> sized PtrToPtr casts whose operand is `AggregateKind::RawPtr`, to turn it into PtrToPtr casts of the base of the aggregate. In this case, this allows us to see that the value of `_7` is just a ptr-to-ptr cast of `_6`.
* Folding a PtrToPtr cast of an operand which is a Transmute cast into just a single Transmute, which (theoretically) allows us to treat `_7` as a transmute into `*mut ()` of the base of the cast of `_10`, which is the place projection of `((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>)`.

However, when applying those two subsequent optimizations, we must *not* update the CastKind of the final cast *unless* we also update the operand of the cast, since the operand may no longer make sense with the updated CastKind.

In this case, this is problematic because the type of `_8` is `*const [()]`, but that operand in assignment statement of `_7` does *not* get turned into something like `((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>)` -- **in other words, `try_to_operand` fails** -- because GVN only turns value nodes into locals or consts, not projections of locals. So we fail to update the operand, but we still update the CastKind to Transmute, which means we now are transmuting types of different sizes (a wide pointer and a thin pointer).

r? `@scottmcm` or `@cjgillot`

Fixes #136361
Fixes #135997
2025-02-07 06:26:41 +00:00
Michael Goulet
de7d4a840e Don't reset cast kind without also updating the operand in simplify_cast 2025-02-06 18:39:35 +00:00
Michael Goulet
c215e80aa9 Failing test 2025-02-06 18:36:02 +00:00
Matthias Krüger
62cad970e8
Rollup merge of #136235 - oli-obk:transmuty-pat-tys, r=RalfJung
Pretty print pattern type values with transmute if they don't satisfy their pattern

Instead of printing `0_u32 is 1..`, we now print the default fallback rendering that we also use for invalid bools, chars, ...: `{transmute(0x00000000): (u32) is 1..=}`.

These cases can occur in mir dumps when const prop propagates a constant across a safety check that would prevent the actually UB value from existing. That's fine though, as it's dead code and we always need to allow UB in dead code.

follow-up to https://github.com/rust-lang/rust/pull/136176

cc ``@compiler-errors`` ``@scottmcm``

r? ``@RalfJung`` because of the interpreter changes
2025-02-06 13:09:58 +01:00
Zalathar
20d051ec87 coverage: Defer part of counter-creation until codegen 2025-02-06 21:44:31 +11:00
Zalathar
ee7dc06cf1 coverage: Store BCB node IDs in mappings, and resolve them in codegen
Even though the coverage graph itself is no longer available during codegen,
its nodes can still be used as opaque IDs.
2025-02-06 21:44:29 +11:00
Oli Scherer
ab3115990d Pretty print pattern type values with transmute if they don't satisfy their pattern 2025-02-05 14:56:41 +00:00
许杰友 Jieyou Xu (Joe)
def44600d1
Rollup merge of #135964 - ehuss:cenum_impl_drop_cast, r=Nadrieril
Make cenum_impl_drop_cast a hard error

This changes the `cenum_impl_drop_cast` lint to be a hard error. This lint has been deny-by-default and warning in dependencies since https://github.com/rust-lang/rust/pull/97652 about 2.5 years ago.

Closes https://github.com/rust-lang/rust/issues/73333
2025-02-05 19:09:33 +08:00
Jacob Pratt
d31e137d6a
Rollup merge of #136167 - pitaj:new_range, r=Nadrieril
Implement unstable `new_range` feature

Switches `a..b`, `a..`, and `a..=b` to resolve to the new range types.

For rust-lang/rfcs#3550
Tracking issue #123741

also adds the re-export that was missed in the original implementation of `new_range_api`
2025-02-04 05:36:52 -05:00
Bastian Kersting
b151b513ba Insert null checks for pointer dereferences when debug assertions are enabled
Similar to how the alignment is already checked, this adds a check
for null pointer dereferences in debug mode. It is implemented similarly
to the alignment check as a MirPass.

This is related to a 2025H1 project goal for better UB checks in debug
mode: https://github.com/rust-lang/rust-project-goals/pull/177.
2025-01-31 11:13:34 +00:00
Peter Jaszkowiak
95eaadc773 std::range 2025-01-30 20:37:56 -07:00
León Orell Valerian Liehr
f49ad60fee
Rollup merge of #136176 - oli-obk:pattern-type-mir-opts, r=compiler-errors
Render pattern types nicely in mir dumps

avoid falling through to the fallback rendering that just does a hex dump

r? ``@scottmcm``

best reviewed commit by commit
2025-01-29 06:03:24 +01:00
Oli Scherer
fd6713fce1 Make mir dumps more readable 2025-01-28 08:19:31 +00:00
Oli Scherer
7877d86163 Add mir-opt pattern type tests 2025-01-28 08:12:25 +00:00
Michael Goulet
eeecb56b73 Represent the raw pointer for a array length check as a new kind of fake borrow 2025-01-28 00:00:33 +00:00
Michael Goulet
057313b7a6 Reapply "Auto merge of #133734 - scottmcm:lower-indexing-to-ptrmetadata, r=davidtwco,RalfJung"
This reverts commit 122a55bb44.
2025-01-27 23:42:47 +00:00
bors
6365178a6b Auto merge of #128657 - clubby789:optimize-none, r=fee1-dead,WaffleLapkin
Add `#[optimize(none)]`

cc #54882

This extends the `optimize` attribute to add `none`, which corresponds to the LLVM `OptimizeNone` attribute.

Not sure if an MCP is required for this, happy to file one if so.
2025-01-25 05:50:36 +00:00
Matthias Krüger
99e34a4ea0
Rollup merge of #135976 - WaffleLapkin:tailcall-nodrop, r=oli-obk
Don't drop types with no drop glue when building drops for tailcalls

this is required as otherwise drops of `&mut` refs count as a usage of a
'two-phase temporary' causing an ICE.

fixes #128097

The underlying issue is that the current code generates drops for `&mut` which are later counted as a second use of a two-phase temporary:

`bat t.rs -p`
```rust
#![expect(incomplete_features)]
#![feature(explicit_tail_calls)]

fn f(x: &mut ()) {
    let _y = String::new();
    become f(x);
}

fn main() {}
```
`rustc t.rs -Zdump_mir=f`
```text
error: internal compiler error: compiler/rustc_borrowck/src/borrow_set.rs:298:17: found two uses for 2-phase borrow temporary _4: bb2[1] and bb3[0]
 --> t.rs:6:5
  |
6 |     become f(x);
  |     ^^^^^^^^^^^

thread 'rustc' panicked at compiler/rustc_borrowck/src/borrow_set.rs:298:17:
Box<dyn Any>
stack backtrace:
[REDACTED]

error: aborting due to 1 previous error
```
`bat ./mir_dump/t.f.-------.renumber.0.mir -p -lrust`
```rust
// MIR for `f` 0 renumber

fn f(_1: &mut ()) -> () {
    debug x => _1;
    let mut _0: ();
    let mut _2: !;
    let _3: std::string::String;
    let mut _4: &mut ();
    scope 1 {
        debug _y => _3;
    }

    bb0: {
        StorageLive(_3);
        _3 = String::new() -> [return: bb1, unwind: bb4];
    }

    bb1: {
        FakeRead(ForLet(None), _3);
        StorageLive(_4);
        _4 = &mut (*_1);
        drop(_3) -> [return: bb2, unwind: bb3];
    }

    bb2: {
        StorageDead(_3);
        tailcall f(Spanned { node: move _4, span: t.rs:6:14: 6:15 (#0) });
    }

    bb3 (cleanup): {
        drop(_4) -> [return: bb4, unwind terminate(cleanup)];
    }

    bb4 (cleanup): {
        resume;
    }
}
```

Note how `_4 is moved into the tail call in `bb2` and dropped in `bb3`.

This PR adds a check that the locals we drop need dropping.

r? `@oli-obk` (feel free to reassign, I'm not sure who would be a good reviewer, but thought you might have an idea)
cc `@beepster4096,` since you wrote the original drop implementation.
2025-01-24 23:25:46 +01:00
Waffle Lapkin
af2ce8b702
don't drop types with no drop glue when tailcalling
this is required as otherwise drops of `&mut` refs count as a usage of a
'two-phase temporary' causing an ICE.
2025-01-24 06:45:19 +01:00
Zalathar
7f10ab2c98 coverage: Tweak FileCheck directives in a mir-opt test 2025-01-24 16:13:12 +11:00
Eric Huss
e0bbeb7a00 Make cenum_impl_drop_cast a hard error
This changes the `cenum_impl_drop_cast` lint to be a hard error. This
lint has been deny-by-default and warning in dependencies since
https://github.com/rust-lang/rust/pull/97652 about 2.5 years ago.

Closes https://github.com/rust-lang/rust/issues/73333
2025-01-23 16:45:19 -08:00
clubby789
7a9661d768 Disable non-required MIR opts with optimize(none)
Co-authored-by: Waffle Lapkin <waffle.lapkin@gmail.com>
2025-01-23 17:40:41 +00:00
Matthias Krüger
bbec1510bb
Rollup merge of #133695 - x17jiri:hint_likely, r=Amanieu
Reexport likely/unlikely in std::hint

Since `likely`/`unlikely` should be working now, we could reexport them in `std::hint`. I'm not sure if this is already approved or if it requires approval

Tracking issue: #26179
2025-01-20 20:58:34 +01:00
Caleb Zulawski
52b42d7187 Update tests for std::simd subtree sync 2025-01-18 21:44:41 -05:00
Rémy Rakic
122a55bb44 Revert "Auto merge of #133734 - scottmcm:lower-indexing-to-ptrmetadata, r=davidtwco,RalfJung"
This reverts commit b57d93d8b9, reversing
changes made to 0aeaa5eb22.
2025-01-18 22:09:35 +00:00
Rémy Rakic
ca1c17c88d Revert "Auto merge of #134330 - scottmcm:no-more-rvalue-len, r=matthewjasper"
This reverts commit e108481f74, reversing
changes made to 303e8bd768.
2025-01-18 22:09:34 +00:00
Matthias Krüger
4aae8d15d6
Rollup merge of #135481 - Zalathar:node-flow, r=oli-obk
coverage: Completely overhaul counter assignment, using node-flow graphs

The existing code for choosing where to put physical counter-increments gets the job done, but is very ad-hoc and hard to modify without introducing tricky regressions.

This PR replaces all of that with a more principled approach, based on the algorithm described in "Optimal measurement points for program frequency counts" (Knuth & Stevenson, 1973).

---

We start by ensuring that our graph has “balanced flow”, i.e. each node's flow (execution count) is equal to the sum of all its in-edge flows, and equal to the sum of all its out-edge flows. That isn't naturally true of control-flow graphs, so we introduce a wrapper type `BalancedFlowGraph` to fix that by introducing synthetic nodes and edges as needed.

Once our graph has balanced flow, the next step is to create another view of that graph in which each node's successors have all been merged into one “supernode”. Consequently, each node's out-edges can be coalesced into a single out-edge to one of those supernodes. Because of the balanced-flow property, the flow of that coalesced edge is equal to the flow of the original node.

Having expressed all of our node flows as edge flows, we can then analyze node flows using techniques for analyzing edge flows. We incrementally build a spanning tree over the merged supernodes, such that each new edge in the spanning tree represents a node whose flow can be computed from that of other nodes.

When this is done, we end up with a list of “counter terms” for each node, describing which nodes need physical counters, and how the remaining nodes can have their flow calculated by adding and subtracting those physical counters.

---

The re-blessed coverage tests show that this results in modest or major improvements for our test programs. Some tests need fewer physical counters, some tests need fewer expression nodes for the same number of physical counters, and some tests show striking reductions in both.
2025-01-16 18:46:09 +01:00
Zalathar
f1300c860e coverage: Completely overhaul counter assignment, using node-flow graphs 2025-01-16 22:07:18 +11:00
Scott McMurray
c18718c9c2 Less unsafe in dangling/without_provenance 2025-01-15 22:17:57 -08:00
Jiri Bobek
c656f879c9 Export likely(), unlikely() and cold_path() in std::hint 2025-01-15 21:42:47 +01:00
Jacob Pratt
81f742954a
Rollup merge of #134498 - oli-obk:push-wmxynprsyxvr, r=compiler-errors
Fix cycle error only occurring with -Zdump-mir

fixes #134205

During mir dumping, we evaluate static items to render their allocations. If a static item refers to itself, its own MIR will have a reference to itself, so during mir dumping we end up evaluating the static again, causing us to try to build MIR again (mir dumping happens during MIR building).

Thus I disabled evaluation of statics during MIR dumps in case the MIR body isn't far enough along yet to be able to be guaranteed cycle free.
2025-01-13 20:43:44 -05:00
Matthias Krüger
988137c040
Rollup merge of #135377 - compiler-errors:impossible-step, r=oli-obk
Make MIR cleanup for functions with impossible predicates into a real MIR pass

It's a bit jarring to see the body of a function with an impossible-to-satisfy where clause suddenly go to a single `unreachable` terminator when looking at the MIR dump output in order, and I discovered it's because we manually replace the body outside of a MIR pass.

Let's make it into a fully flegded MIR pass so it's more clear what it's doing and when it's being applied.
2025-01-12 12:07:58 +01:00
Scott McMurray
7396ec3edb Address PR feedback 2025-01-11 15:56:58 -08:00
Scott McMurray
6e34369ef6 [mir-opt] simplify Repeats that don't actually repeat the operand 2025-01-11 15:56:53 -08:00
Michael Goulet
f1d622678b Make MIR cleanup for functions with impossible predicates into a real MIR pass 2025-01-11 20:50:39 +00:00
bors
7e4077d06f Auto merge of #135274 - saethlin:array-repeats, r=compiler-errors
Add an InstSimplify for repetitive array expressions

I noticed in https://github.com/rust-lang/rust/pull/135068#issuecomment-2569955426 that GVN's implementation of this same transform was quite profitable on the deep-vector benchmark. But of course GVN doesn't run in unoptimized builds, so this is my attempt to write a version of this transform that benefits the deep-vector case and is fast enough to run in InstSimplify.

The benchmark suite indicates that this is effective.
2025-01-11 06:33:55 +00:00
David Wood
3169a4493f
don't collect #[rustc_force_inline] in eager mode 2025-01-10 18:37:57 +00:00
David Wood
f86169a58f
mir_transform: implement forced inlining
Adds `#[rustc_force_inline]` which is similar to always inlining but
reports an error if the inlining was not possible, and which always
attempts to inline annotated items, regardless of optimisation levels.
It can only be applied to free functions to guarantee that the MIR
inliner will be able to resolve calls.
2025-01-10 18:37:54 +00:00
Oli Scherer
15c01eb22c Fix cycle error only occurring with -Zdump-mir 2025-01-10 08:57:54 +00:00
Ben Kimock
a285d202cf Add an InstSimplify for repetitive array expressions 2025-01-09 20:00:32 -05:00
Scott McMurray
b421a56364 Make the aggregate-then-transmute handling more general 2025-01-08 18:46:31 -08:00
Scott McMurray
293f8e8941 Refactor the cast-then-cast cases together, and support transmute-then-transmute 2025-01-08 18:46:30 -08:00
Scott McMurray
03650dd029 Use layout information to detect transparent transmutes 2025-01-08 18:46:30 -08:00
Scott McMurray
8dcc676c92 [mir-opt] GVN some more transmute cases
We already did `Transmute`-then-`PtrToPtr`; this adds the nearly-identical `PtrToPtr`-then-`Transmute`.

It also adds `transmute(Foo(x))` → `transmute(x)`, when `Foo` is a single-field transparent type.  That's useful for things like `NonNull { pointer: p }.as_ptr()`.

Found these as I was looking at MCP807-related changes.
2025-01-08 18:46:30 -08:00
Michael Goulet
c55eefe8bc Try to explain borrow for tail expr temporary drop order change in 2024 2025-01-08 16:02:44 +00:00
Scott McMurray
ad5f912d96 Transmute from NonNull to pointer when elaborating a box deref (MCP807) 2025-01-06 18:43:40 -08:00