Move /src/test to /tests
This commit is contained in:
parent
ca855e6e42
commit
cf2dff2b1e
27592 changed files with 0 additions and 0 deletions
48
tests/incremental/thinlto/cgu_invalidated_via_import.rs
Normal file
48
tests/incremental/thinlto/cgu_invalidated_via_import.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// This test checks that the LTO phase is re-done for CGUs that import something
|
||||
// via ThinLTO and that imported thing changes while the definition of the CGU
|
||||
// stays untouched.
|
||||
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph -O
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-foo",
|
||||
cfg="cfail2",
|
||||
kind="no")]
|
||||
#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-foo",
|
||||
cfg="cfail3",
|
||||
kind="post-lto")]
|
||||
|
||||
#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-bar",
|
||||
cfg="cfail2",
|
||||
kind="pre-lto")]
|
||||
#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-bar",
|
||||
cfg="cfail3",
|
||||
kind="post-lto")]
|
||||
|
||||
mod foo {
|
||||
|
||||
// Trivial functions like this one are imported very reliably by ThinLTO.
|
||||
#[cfg(cfail1)]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
1234
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
// See `cgu_keeps_identical_fn.rs` for why this is different
|
||||
// from the other version of this function.
|
||||
12345
|
||||
}
|
||||
}
|
||||
|
||||
pub mod bar {
|
||||
use foo::inlined_fn;
|
||||
|
||||
pub fn caller() -> u32 {
|
||||
inlined_fn()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// revisions: cfail1 cfail2
|
||||
// build-pass
|
||||
|
||||
// rust-lang/rust#69798:
|
||||
//
|
||||
// This is analogous to cgu_invalidated_when_import_added, but it covers a
|
||||
// problem uncovered where a change to the *export* set caused a link failure
|
||||
// when reusing post-LTO optimized object code.
|
||||
|
||||
pub struct Foo {}
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping Foo");
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn run() {
|
||||
thread_local! { pub static FOO : Foo = Foo { } ; }
|
||||
|
||||
#[cfg(cfail2)]
|
||||
{
|
||||
FOO.with(|_f| ())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() { run() }
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// revisions: cfail1 cfail2
|
||||
// build-pass
|
||||
|
||||
// rust-lang/rust#69798:
|
||||
//
|
||||
// This is analogous to cgu_invalidated_when_export_added, but it covers the
|
||||
// other direction. This is analogous to cgu_invalidated_when_import_added: we
|
||||
// include it, because it may uncover bugs in variant implementation strategies.
|
||||
|
||||
pub struct Foo {}
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) {
|
||||
println!("Dropping Foo");
|
||||
}
|
||||
}
|
||||
#[no_mangle]
|
||||
pub extern "C" fn run() {
|
||||
thread_local! { pub static FOO : Foo = Foo { } ; }
|
||||
|
||||
#[cfg(cfail1)]
|
||||
{
|
||||
FOO.with(|_f| ())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() { run() }
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// revisions: cfail1 cfail2
|
||||
// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
|
||||
// build-pass
|
||||
|
||||
// rust-lang/rust#59535:
|
||||
//
|
||||
// This is analogous to cgu_invalidated_when_import_removed.rs, but it covers
|
||||
// the other direction:
|
||||
//
|
||||
// We start with a call-graph like `[A] -> [B -> D] [C]` (where the letters are
|
||||
// functions and the modules are enclosed in `[]`), and add a new call `D <- C`,
|
||||
// yielding the new call-graph: `[A] -> [B -> D] <- [C]`
|
||||
//
|
||||
// The effect of this is that the compiler previously classfied `D` as internal
|
||||
// and the import-set of `[A]` to be just `B`. But after adding the `D <- C` call,
|
||||
// `D` is no longer classified as internal, and the import-set of `[A]` becomes
|
||||
// both `B` and `D`.
|
||||
//
|
||||
// We check this case because an early proposed pull request included an
|
||||
// assertion that the import-sets monotonically decreased over time, a claim
|
||||
// which this test case proves to be false.
|
||||
|
||||
fn main() {
|
||||
foo::foo();
|
||||
bar::baz();
|
||||
}
|
||||
|
||||
mod foo {
|
||||
|
||||
// In cfail1, ThinLTO decides that foo() does not get inlined into main, and
|
||||
// instead bar() gets inlined into foo().
|
||||
// In cfail2, foo() gets inlined into main.
|
||||
pub fn foo(){
|
||||
bar()
|
||||
}
|
||||
|
||||
// This function needs to be big so that it does not get inlined by ThinLTO
|
||||
// but *does* get inlined into foo() when it is declared `internal` in
|
||||
// cfail1 (alone).
|
||||
pub fn bar(){
|
||||
println!("quux1");
|
||||
println!("quux2");
|
||||
println!("quux3");
|
||||
println!("quux4");
|
||||
println!("quux5");
|
||||
println!("quux6");
|
||||
println!("quux7");
|
||||
println!("quux8");
|
||||
println!("quux9");
|
||||
}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
|
||||
#[inline(never)]
|
||||
pub fn baz() {
|
||||
#[cfg(cfail2)]
|
||||
{
|
||||
crate::foo::bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// revisions: cfail1 cfail2
|
||||
// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
|
||||
// build-pass
|
||||
|
||||
// rust-lang/rust#59535:
|
||||
//
|
||||
// Consider a call-graph like `[A] -> [B -> D] <- [C]` (where the letters are
|
||||
// functions and the modules are enclosed in `[]`)
|
||||
//
|
||||
// In our specific instance, the earlier compilations were inlining the call
|
||||
// to`B` into `A`; thus `A` ended up with an external reference to the symbol `D`
|
||||
// in its object code, to be resolved at subsequent link time. The LTO import
|
||||
// information provided by LLVM for those runs reflected that information: it
|
||||
// explicitly says during those runs, `B` definition and `D` declaration were
|
||||
// imported into `[A]`.
|
||||
//
|
||||
// The change between incremental builds was that the call `D <- C` was removed.
|
||||
//
|
||||
// That change, coupled with other decisions within `rustc`, made the compiler
|
||||
// decide to make `D` an internal symbol (since it was no longer accessed from
|
||||
// other codegen units, this makes sense locally). And then the definition of
|
||||
// `D` was inlined into `B` and `D` itself was eliminated entirely.
|
||||
//
|
||||
// The current LTO import information reported that `B` alone is imported into
|
||||
// `[A]` for the *current compilation*. So when the Rust compiler surveyed the
|
||||
// dependence graph, it determined that nothing `[A]` imports changed since the
|
||||
// last build (and `[A]` itself has not changed either), so it chooses to reuse
|
||||
// the object code generated during the previous compilation.
|
||||
//
|
||||
// But that previous object code has an unresolved reference to `D`, and that
|
||||
// causes a link time failure!
|
||||
|
||||
fn main() {
|
||||
foo::foo();
|
||||
bar::baz();
|
||||
}
|
||||
|
||||
mod foo {
|
||||
|
||||
// In cfail1, foo() gets inlined into main.
|
||||
// In cfail2, ThinLTO decides that foo() does not get inlined into main, and
|
||||
// instead bar() gets inlined into foo(). But faulty logic in our incr.
|
||||
// ThinLTO implementation thought that `main()` is unchanged and thus reused
|
||||
// the object file still containing a call to the now non-existent bar().
|
||||
pub fn foo(){
|
||||
bar()
|
||||
}
|
||||
|
||||
// This function needs to be big so that it does not get inlined by ThinLTO
|
||||
// but *does* get inlined into foo() once it is declared `internal` in
|
||||
// cfail2.
|
||||
pub fn bar(){
|
||||
println!("quux1");
|
||||
println!("quux2");
|
||||
println!("quux3");
|
||||
println!("quux4");
|
||||
println!("quux5");
|
||||
println!("quux6");
|
||||
println!("quux7");
|
||||
println!("quux8");
|
||||
println!("quux9");
|
||||
}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
|
||||
#[inline(never)]
|
||||
pub fn baz() {
|
||||
#[cfg(cfail1)]
|
||||
{
|
||||
crate::foo::bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
49
tests/incremental/thinlto/cgu_keeps_identical_fn.rs
Normal file
49
tests/incremental/thinlto/cgu_keeps_identical_fn.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// This test is almost identical to `cgu_invalided_via_import`, except that
|
||||
// the two versions of `inline_fn` are identical. Neither version of `inlined_fn`
|
||||
// ends up with any spans in its LLVM bitecode, so LLVM is able to skip
|
||||
// re-building any modules which import 'inlined_fn'
|
||||
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph -O
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type = "rlib"]
|
||||
#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")]
|
||||
#![rustc_expected_cgu_reuse(
|
||||
module = "cgu_keeps_identical_fn-foo",
|
||||
cfg = "cfail3",
|
||||
kind = "post-lto"
|
||||
)]
|
||||
#![rustc_expected_cgu_reuse(
|
||||
module = "cgu_keeps_identical_fn-bar",
|
||||
cfg = "cfail2",
|
||||
kind = "post-lto"
|
||||
)]
|
||||
#![rustc_expected_cgu_reuse(
|
||||
module = "cgu_keeps_identical_fn-bar",
|
||||
cfg = "cfail3",
|
||||
kind = "post-lto"
|
||||
)]
|
||||
|
||||
mod foo {
|
||||
|
||||
// Trivial functions like this one are imported very reliably by ThinLTO.
|
||||
#[cfg(any(cfail1, cfail4))]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
1234
|
||||
}
|
||||
|
||||
#[cfg(not(any(cfail1, cfail4)))]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
1234
|
||||
}
|
||||
}
|
||||
|
||||
pub mod bar {
|
||||
use foo::inlined_fn;
|
||||
|
||||
pub fn caller() -> u32 {
|
||||
inlined_fn()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// This test checks that a change in a CGU does not invalidate an unrelated CGU
|
||||
// during incremental ThinLTO.
|
||||
|
||||
// revisions: cfail1 cfail2 cfail3
|
||||
// compile-flags: -Z query-dep-graph -O
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![crate_type="rlib"]
|
||||
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-foo",
|
||||
cfg="cfail2",
|
||||
kind="no")]
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-foo",
|
||||
cfg="cfail3",
|
||||
kind="post-lto")]
|
||||
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-bar",
|
||||
cfg="cfail2",
|
||||
kind="pre-lto")]
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-bar",
|
||||
cfg="cfail3",
|
||||
kind="post-lto")]
|
||||
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-baz",
|
||||
cfg="cfail2",
|
||||
kind="post-lto")]
|
||||
#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-baz",
|
||||
cfg="cfail3",
|
||||
kind="post-lto")]
|
||||
mod foo {
|
||||
|
||||
#[cfg(cfail1)]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
1234
|
||||
}
|
||||
|
||||
#[cfg(not(cfail1))]
|
||||
pub fn inlined_fn() -> u32 {
|
||||
// See `cgu_keeps_identical_fn.rs` for why this is different
|
||||
// from the other version of this function.
|
||||
12345
|
||||
}
|
||||
}
|
||||
|
||||
pub mod bar {
|
||||
use foo::inlined_fn;
|
||||
|
||||
pub fn caller() -> u32 {
|
||||
inlined_fn()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod baz {
|
||||
pub fn unrelated_to_other_fns() -> u64 {
|
||||
0xbeef
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue