Rollup merge of #143271 - cjgillot:gvn-types, r=oli-obk

Store the type of each GVN value

MIR is fully typed, so type information is an integral part of what defines a value. GVN currently tries to circumvent storing types, which creates all sorts of complexities.

This PR stores the type along with the enum `Value` when defining a value index. This allows to simplify a lot of code.

Fixes rust-lang/rust#128094
Fixes rust-lang/rust#135128

r? ``````@ghost`````` for perf
This commit is contained in:
Matthias Krüger 2025-07-18 04:27:50 +02:00 committed by GitHub
commit b252014673
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 309 additions and 310 deletions

File diff suppressed because it is too large Load diff

View file

@ -56,7 +56,7 @@ pub unsafe fn undef_union_as_integer() -> u32 {
pub unsafe fn unreachable_direct() -> ! {
// CHECK-LABEL: fn unreachable_direct(
// CHECK: = const ();
// CHECK: = const () as Never (Transmute);
// CHECK: = const ZeroSized: Never;
let x: Never = unsafe { transmute(()) };
match x {}
}

View file

@ -15,7 +15,7 @@
- _2 = ();
- _1 = move _2 as Never (Transmute);
+ _2 = const ();
+ _1 = const () as Never (Transmute);
+ _1 = const ZeroSized: Never;
unreachable;
}
}

View file

@ -15,7 +15,7 @@
- _2 = ();
- _1 = move _2 as Never (Transmute);
+ _2 = const ();
+ _1 = const () as Never (Transmute);
+ _1 = const ZeroSized: Never;
unreachable;
}
}

View file

@ -18,7 +18,8 @@
bb0: {
_4 = copy _1 as *const T (PtrToPtr);
_5 = PtrMetadata(copy _4);
- _5 = PtrMetadata(copy _4);
+ _5 = const ();
_6 = copy _1 as *const (&A, [T]) (PtrToPtr);
- _7 = PtrMetadata(copy _6);
+ _7 = PtrMetadata(copy _1);

View file

@ -18,7 +18,8 @@
bb0: {
_4 = copy _1 as *const T (PtrToPtr);
_5 = PtrMetadata(copy _4);
- _5 = PtrMetadata(copy _4);
+ _5 = const ();
_6 = copy _1 as *const (&A, [T]) (PtrToPtr);
- _7 = PtrMetadata(copy _6);
+ _7 = PtrMetadata(copy _1);

View file

@ -869,7 +869,7 @@ fn generic_cast_metadata<T, A: ?Sized, B: ?Sized>(ps: *const [T], pa: *const A,
// Metadata usize -> (), do not optimize.
// CHECK: [[T:_.+]] = copy _1 as
// CHECK-NEXT: PtrMetadata(copy [[T]])
// CHECK-NEXT: const ();
let t1 = CastPtrToPtr::<_, *const T>(ps);
let m1 = PtrMetadata(t1);

View file

@ -109,7 +109,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb4: {
StorageLive(_15);
_14 = &mut _13;
_15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
}
@ -120,7 +119,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb6: {
StorageDead(_15);
StorageDead(_13);
drop(_2) -> [return: bb7, unwind continue];
}
@ -135,14 +133,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
StorageLive(_19);
_19 = &_2;
StorageLive(_20);
_20 = (copy _17, copy _18);
_20 = copy ((_15 as Some).0: (usize, &T));
_21 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
}
bb9: {
StorageDead(_20);
StorageDead(_19);
StorageDead(_15);
goto -> bb4;
}

View file

@ -1,15 +1,19 @@
//@ known-bug: rust-lang/rust#128094
//! Verify that we do not ICE when a coroutine body is malformed.
//@ compile-flags: -Zmir-enable-passes=+GVN
//@ edition: 2018
pub enum Request {
TestSome(T),
//~^ ERROR cannot find type `T` in this scope [E0412]
}
pub async fn handle_event(event: Request) {
async move {
static instance: Request = Request { bar: 17 };
//~^ ERROR expected struct, variant or union type, found enum `Request` [E0574]
&instance
}
.await;
}
fn main() {}

View file

@ -0,0 +1,26 @@
error[E0412]: cannot find type `T` in this scope
--> $DIR/gvn-nonsensical-coroutine-layout.rs:6:14
|
LL | TestSome(T),
| ^ not found in this scope
|
help: you might be missing a type parameter
|
LL | pub enum Request<T> {
| +++
error[E0574]: expected struct, variant or union type, found enum `Request`
--> $DIR/gvn-nonsensical-coroutine-layout.rs:12:36
|
LL | static instance: Request = Request { bar: 17 };
| ^^^^^^^ not a struct, variant or union type
|
help: consider importing this struct instead
|
LL + use std::error::Request;
|
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0412, E0574.
For more information about an error, try `rustc --explain E0412`.

View file

@ -1,13 +1,16 @@
//@ known-bug: #135128
//! Verify that we do not ICE when optimizing bodies with nonsensical bounds.
//@ compile-flags: -Copt-level=1
//@ edition: 2021
//@ build-pass
#![feature(trivial_bounds)]
async fn return_str() -> str
where
str: Sized,
//~^ WARN trait bound str: Sized does not depend on any type or lifetime parameters
{
*"Sized".to_string().into_boxed_str()
}
fn main() {}

View file

@ -0,0 +1,10 @@
warning: trait bound str: Sized does not depend on any type or lifetime parameters
--> $DIR/gvn-nonsensical-sized-str.rs:10:10
|
LL | str: Sized,
| ^^^^^
|
= note: `#[warn(trivial_bounds)]` on by default
warning: 1 warning emitted