rust/tests/mir-opt/sroa/structs.rs
2023-10-19 15:51:52 +00:00

124 lines
2.6 KiB
Rust

// skip-filecheck
// unit-test: ScalarReplacementOfAggregates
// compile-flags: -Cpanic=abort
// no-prefer-dynamic
struct Tag(usize);
#[repr(C)]
struct S(Tag, Tag, Tag);
impl Drop for Tag {
#[inline(never)]
fn drop(&mut self) {}
}
pub fn dropping() {
S(Tag(0), Tag(1), Tag(2)).1;
}
pub fn enums(a: usize) -> usize {
if let Some(a) = Some(a) { a } else { 0 }
}
pub fn structs(a: f32) -> f32 {
struct U {
_foo: usize,
a: f32,
}
U { _foo: 0, a }.a
}
pub fn unions(a: f32) -> u32 {
union Repr {
f: f32,
u: u32,
}
unsafe { Repr { f: a }.u }
}
#[derive(Copy, Clone)]
struct Foo {
a: u8,
b: (),
c: &'static str,
d: Option<isize>,
}
fn g() -> u32 {
3
}
pub fn flat() {
let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) };
let _ = a;
let _ = b;
let _ = c;
let _ = d;
}
#[repr(C)]
struct Escaping {
a: u32,
b: u32,
c: u32,
}
fn f(a: *const u32) {
println!("{}", unsafe { *a.add(2) });
}
// `f` uses the `&e.a` to access `e.c`. This is UB according to Miri today; however,
// T-opsem has not finalized that decision and as such rustc should not rely on
// it. If SROA were to rely on it, it would be (almost) correct to turn `e` into
// three distinct locals - one for each field - and pass a reference to only one
// of them to `f`. However, this would lead to a miscompilation because `b` and `c`
// might no longer appear right after `a` in memory.
pub fn escaping() {
f(&Escaping { a: 1, b: 2, c: g() }.a);
}
fn copies(x: Foo) {
let y = x;
let t = y.a;
let u = y.c;
let z = y;
let a = z.b;
}
fn ref_copies(x: &Foo) {
let y = *x;
let t = y.a;
let u = y.c;
}
fn constant() {
const U: (usize, u8) = (5, 9);
let y = U;
let t = y.0;
let u = y.1;
}
fn main() {
dropping();
enums(5);
structs(5.);
unions(5.);
flat();
escaping();
copies(Foo { a: 5, b: (), c: "a", d: Some(-4) });
ref_copies(&Foo { a: 5, b: (), c: "a", d: Some(-4) });
constant();
}
// EMIT_MIR structs.dropping.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.enums.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.structs.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.unions.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.flat.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.escaping.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.copies.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.ref_copies.ScalarReplacementOfAggregates.diff
// EMIT_MIR structs.constant.ScalarReplacementOfAggregates.diff