Skip to content

Add FileCheck annotations to MIR-opt SROA tests #120455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/mir-opt/remove_storage_markers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
// unit-test: RemoveStorageMarkers

Expand All @@ -8,6 +7,10 @@

// EMIT_MIR remove_storage_markers.main.RemoveStorageMarkers.diff
fn main() {
// CHECK-LABEL: fn main(

// CHECK-NOT: StorageDead
// CHECK-NOT: StorageLive
let mut sum = 0;
for i in 0..10 {
sum += i;
Expand Down
5 changes: 4 additions & 1 deletion tests/mir-opt/simplify_if.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#[inline(never)]
fn noop() {}

// EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff
fn main() {
// CHECK-LABEL: fn main(

// CHECK: bb0: {
// CHECK-NEXT: return;
if false {
noop();
}
Expand Down
5 changes: 4 additions & 1 deletion tests/mir-opt/sroa/lifetimes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// skip-filecheck
// unit-test: ScalarReplacementOfAggregates
// compile-flags: -Cpanic=abort
// no-prefer-dynamic
Expand All @@ -16,6 +15,10 @@ struct Foo<T: Err> {

// EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff
fn foo<T: Err>() {
// CHECK-LABEL: fn foo(

// CHECK-NOT: [foo:_.*]: Foo
// CHECK-NOT: Box<dyn std::fmt::Display + 'static>
let foo: Foo<T> = Foo {
x: Ok(Box::new(5_u32)),
y: 7_u32,
Expand Down
125 changes: 119 additions & 6 deletions tests/mir-opt/sroa/structs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// skip-filecheck
// unit-test: ScalarReplacementOfAggregates
// compile-flags: -Cpanic=abort
// no-prefer-dynamic
Expand All @@ -13,28 +12,68 @@ impl Drop for Tag {
fn drop(&mut self) {}
}

/// Check that SROA excludes structs with a `Drop` implementation.
pub fn dropping() {
// CHECK-LABEL: fn dropping(

// CHECK: [[aggregate:_[0-9]+]]: S;

// CHECK: bb0: {
// CHECK: [[aggregate]] = S
S(Tag(0), Tag(1), Tag(2)).1;
}

/// Check that SROA excludes enums.
pub fn enums(a: usize) -> usize {
// CHECK-LABEL: fn enums(

// CHECK: [[enum:_[0-9]+]]: std::option::Option<usize>;

// CHECK: bb0: {
// CHECK: [[enum]] = Option::<usize>::Some
// CHECK: _5 = (([[enum]] as Some).0: usize)
// CHECK: _0 = _5
if let Some(a) = Some(a) { a } else { 0 }
}

/// Check that SROA destructures `U`.
pub fn structs(a: f32) -> f32 {
// CHECK-LABEL: fn structs(
struct U {
_foo: usize,
a: f32,
}

// CHECK: [[ret:_0]]: f32;
// CHECK: [[struct:_[0-9]+]]: structs::U;
// CHECK: [[a_tmp:_[0-9]+]]: f32;
// CHECK: [[foo:_[0-9]+]]: usize;
// CHECK: [[a_ret:_[0-9]+]]: f32;

// CHECK: bb0: {
// CHECK-NOT: [[struct]]
// CHECK: [[a_tmp]] = _1;
// CHECK-NOT: [[struct]]
// CHECK: [[foo]] = const 0_usize;
// CHECK-NOT: [[struct]]
// CHECK: [[a_ret]] = move [[a_tmp]];
// CHECK-NOT: [[struct]]
// CHECK: _0 = [[a_ret]];
// CHECK-NOT: [[struct]]
U { _foo: 0, a }.a
}

/// Check that SROA excludes unions.
pub fn unions(a: f32) -> u32 {
// CHECK-LABEL: fn unions(
union Repr {
f: f32,
u: u32,
}
// CHECK: [[union:_[0-9]+]]: unions::Repr;

// CHECK: bb0: {
// CHECK: [[union]] = Repr {
// CHECK: _0 = ([[union]].1: u32)
unsafe { Repr { f: a }.u }
}

Expand All @@ -46,11 +85,21 @@ struct Foo {
d: Option<isize>,
}

fn g() -> u32 {
3
}

/// Check that non-escaping uses of a struct are destructured.
pub fn flat() {
// CHECK-LABEL: fn flat(

// CHECK: [[struct:_[0-9]+]]: Foo;

// CHECK: bb0: {
// CHECK: [[init_unit:_[0-9]+]] = ();
// CHECK: [[init_opt_isize:_[0-9]+]] = Option::<isize>::Some

// CHECK: [[destr_five:_[0-9]+]] = const 5_u8;
// CHECK: [[destr_unit:_[0-9]+]] = move [[init_unit]];
// CHECK: [[destr_a:_[0-9]+]] = const "a";
// CHECK: [[destr_opt_isize:_[0-9]+]] = move [[init_opt_isize]];

let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) };
let _ = a;
let _ = b;
Expand All @@ -65,6 +114,10 @@ struct Escaping {
c: u32,
}

fn g() -> u32 {
3
}

fn f(a: *const u32) {
println!("{}", unsafe { *a.add(2) });
}
Expand All @@ -76,31 +129,91 @@ fn f(a: *const u32) {
// 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() {
// CHECK-LABEL: fn escaping(

// CHECK: [[ptr:_[0-9]+]]: *const u32;
// CHECK: [[ref:_[0-9]+]]: &u32;
// CHECK: [[struct:_[0-9]+]]: Escaping;
// CHECK: [[a:_[0-9]+]]: u32;

// CHECK: bb0: {
// CHECK: [[struct]] = Escaping {
// CHECK: [[ref]] = &([[struct]].0
// CHECK: [[ptr]] = &raw const (*[[ref]]);
f(&Escaping { a: 1, b: 2, c: g() }.a);
}

/// Check that copies from an internal struct are destructured and reassigned to
/// the original struct.
fn copies(x: Foo) {
// CHECK-LABEL: fn copies(

// CHECK: [[external:_[0-9]+]]: Foo) ->
// CHECK: [[internal:_[0-9]+]]: Foo;
// CHECK: [[byte:_[0-9]+]]: u8;
// CHECK: [[unit:_[0-9]+]]: ();
// CHECK: [[str:_[0-9]+]]: &str;
// CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>;

// CHECK: bb0: {
// CHECK: [[byte]] = ([[external]].0
// CHECK: [[unit]] = ([[external]].1
// CHECK: [[str]] = ([[external]].2
// CHECK: [[opt_isize]] = ([[external]].3

let y = x;
let t = y.a;
let u = y.c;
let z = y;
let a = z.b;
}

/// Check that copies from an internal struct are destructured and reassigned to
/// the original struct.
fn ref_copies(x: &Foo) {
// CHECK-LABEL: fn ref_copies(

// CHECK: [[external:_[0-9]+]]: &Foo) ->
// CHECK: [[internal:_[0-9]+]]: Foo;
// CHECK: [[byte:_[0-9]+]]: u8;
// CHECK: [[unit:_[0-9]+]]: ();
// CHECK: [[str:_[0-9]+]]: &str;
// CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>;

// CHECK: bb0: {
// CHECK: [[byte]] = ((*[[external]]).0
// CHECK: [[unit]] = ((*[[external]]).1
// CHECK: [[str]] = ((*[[external]]).2
// CHECK: [[opt_isize]] = ((*[[external]]).3

let y = *x;
let t = y.a;
let u = y.c;
}

/// Check that deaggregated assignments from constants are placed after the constant's
/// assignment. Also check that copying field accesses from the copy of the constant are
/// reassigned to copy from the constant.
fn constant() {
// CHECK-LABEL: constant(

// CHECK: [[constant:_[0-9]+]]: (usize, u8);
// CHECK: [[t:_[0-9]+]]: usize;
// CHECK: [[u:_[0-9]+]]: u8;

// CHECK: bb0: {
// CHECK-NOT: [[constant]]
// CHECK: [[constant]] = const
// CHECK: [[t]] = move ([[constant]].0: usize)
// CHECK: [[u]] = move ([[constant]].1: u8)
const U: (usize, u8) = (5, 9);
let y = U;
let t = y.0;
let u = y.1;
}

fn main() {
// CHECK-LABEL: fn main(
dropping();
enums(5);
structs(5.);
Expand Down