From 1de93a78147126dcb864e070734532a02dde56cc Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 20 May 2019 11:43:38 +0200 Subject: [PATCH] Add a smoketest for combining PGO with xLTO. --- .../cross-lang-lto-pgo-smoketest/Makefile | 87 +++++++++++++++++++ .../cross-lang-lto-pgo-smoketest/clib.c | 9 ++ .../cross-lang-lto-pgo-smoketest/cmain.c | 12 +++ .../cross-lang-lto-pgo-smoketest/main.rs | 11 +++ .../cross-lang-lto-pgo-smoketest/rustlib.rs | 12 +++ 5 files changed, 131 insertions(+) create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs create mode 100644 src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile new file mode 100644 index 00000000000..59a7d61892f --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile @@ -0,0 +1,87 @@ +# needs-matching-clang + +# This test makes sure that cross-language inlining can be used in conjunction +# with profile-guided optimization. The test only tests that the whole workflow +# can be executed without anything crashing. It does not test whether PGO or +# xLTO have any specific effect on the generated code. + +-include ../tools.mk + +COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1 + +# LLVM doesn't support instrumenting binaries that use SEH: +# https://bugs.llvm.org/show_bug.cgi?id=41279 +# +# Things work fine with -Cpanic=abort though. +ifdef IS_MSVC +COMMON_FLAGS+= -Cpanic=abort +endif + +all: cpp-executable rust-executable + +cpp-executable: + $(RUSTC) -Clinker-plugin-lto=on \ + -Zpgo-gen="$(TMPDIR)"/cpp-profdata \ + -o "$(TMPDIR)"/librustlib-xlto.a \ + $(COMMON_FLAGS) \ + ./rustlib.rs + $(CLANG) -flto=thin \ + -fprofile-generate="$(TMPDIR)"/cpp-profdata \ + -fuse-ld=lld \ + -L "$(TMPDIR)" \ + -lrustlib-xlto \ + -o "$(TMPDIR)"/cmain \ + -O3 \ + ./cmain.c + $(TMPDIR)/cmain + # Postprocess the profiling data so it can be used by the compiler + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/cpp-profdata/merged.profdata \ + "$(TMPDIR)"/cpp-profdata/default_*.profraw + $(RUSTC) -Clinker-plugin-lto=on \ + -Zpgo-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ + -o "$(TMPDIR)"/librustlib-xlto.a \ + $(COMMON_FLAGS) \ + ./rustlib.rs + $(CLANG) -flto=thin \ + -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ + -fuse-ld=lld \ + -L "$(TMPDIR)" \ + -lrustlib-xlto \ + -o "$(TMPDIR)"/cmain \ + -O3 \ + ./cmain.c + +rust-executable: + exit + $(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3 + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on \ + -Zpgo-gen="$(TMPDIR)"/rs-profdata \ + -L$(TMPDIR) \ + $(COMMON_FLAGS) \ + -Clinker=$(CLANG) \ + -Clink-arg=-fuse-ld=lld \ + -o $(TMPDIR)/rsmain \ + ./main.rs + $(TMPDIR)/rsmain + # Postprocess the profiling data so it can be used by the compiler + "$(LLVM_BIN_DIR)"/llvm-profdata merge \ + -o "$(TMPDIR)"/rs-profdata/merged.profdata \ + "$(TMPDIR)"/rs-profdata/default_*.profraw + $(CLANG) ./clib.c \ + -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ + -flto=thin \ + -c \ + -o $(TMPDIR)/clib.o \ + -O3 + rm "$(TMPDIR)"/libxyz.a + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on \ + -Zpgo-use="$(TMPDIR)"/rs-profdata/merged.profdata \ + -L$(TMPDIR) \ + $(COMMON_FLAGS) \ + -Clinker=$(CLANG) \ + -Clink-arg=-fuse-ld=lld \ + -o $(TMPDIR)/rsmain \ + ./main.rs diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c new file mode 100644 index 00000000000..90f33f24dc4 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/clib.c @@ -0,0 +1,9 @@ +#include + +uint32_t c_always_inlined() { + return 1234; +} + +__attribute__((noinline)) uint32_t c_never_inlined() { + return 12345; +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c new file mode 100644 index 00000000000..e3f24828be3 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/cmain.c @@ -0,0 +1,12 @@ +#include + +// A trivial function defined in Rust, returning a constant value. This should +// always be inlined. +uint32_t rust_always_inlined(); + + +uint32_t rust_never_inlined(); + +int main(int argc, char** argv) { + return (rust_never_inlined() + rust_always_inlined()) * 0; +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs new file mode 100644 index 00000000000..8129dcb85d9 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/main.rs @@ -0,0 +1,11 @@ +#[link(name = "xyz")] +extern "C" { + fn c_always_inlined() -> u32; + fn c_never_inlined() -> u32; +} + +fn main() { + unsafe { + println!("blub: {}", c_always_inlined() + c_never_inlined()); + } +} diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs new file mode 100644 index 00000000000..8a74d74a420 --- /dev/null +++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/rustlib.rs @@ -0,0 +1,12 @@ +#![crate_type="staticlib"] + +#[no_mangle] +pub extern "C" fn rust_always_inlined() -> u32 { + 42 +} + +#[no_mangle] +#[inline(never)] +pub extern "C" fn rust_never_inlined() -> u32 { + 421 +}