summaryrefslogtreecommitdiffstats
path: root/tests/run-make/pgo-indirect-call-promotion
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make/pgo-indirect-call-promotion')
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/Makefile26
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/filecheck-patterns.txt16
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/interesting.rs56
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/main.rs14
-rw-r--r--tests/run-make/pgo-indirect-call-promotion/opaque.rs7
5 files changed, 119 insertions, 0 deletions
diff --git a/tests/run-make/pgo-indirect-call-promotion/Makefile b/tests/run-make/pgo-indirect-call-promotion/Makefile
new file mode 100644
index 000000000..45302215c
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/Makefile
@@ -0,0 +1,26 @@
+# needs-profiler-support
+# ignore-windows-gnu
+
+# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
+# properly. Since we only have GCC on the CI ignore the test for now.
+
+include ../tools.mk
+
+all:
+ # We don't compile `opaque` with either optimizations or instrumentation.
+ # We don't compile `opaque` with either optimizations or instrumentation.
+ $(RUSTC) $(COMMON_FLAGS) opaque.rs
+ # Compile the test program with instrumentation
+ mkdir -p "$(TMPDIR)"/prof_data_dir
+ $(RUSTC) $(COMMON_FLAGS) interesting.rs \
+ -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O -Ccodegen-units=1
+ $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O
+ # The argument below generates to the expected branch weights
+ $(call RUN,main) || exit 1
+ "$(LLVM_BIN_DIR)"/llvm-profdata merge \
+ -o "$(TMPDIR)"/prof_data_dir/merged.profdata \
+ "$(TMPDIR)"/prof_data_dir
+ $(RUSTC) $(COMMON_FLAGS) interesting.rs \
+ -Cprofile-use="$(TMPDIR)"/prof_data_dir/merged.profdata -O \
+ -Ccodegen-units=1 --emit=llvm-ir
+ cat "$(TMPDIR)"/interesting.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt
diff --git a/tests/run-make/pgo-indirect-call-promotion/filecheck-patterns.txt b/tests/run-make/pgo-indirect-call-promotion/filecheck-patterns.txt
new file mode 100644
index 000000000..e19c78350
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/filecheck-patterns.txt
@@ -0,0 +1,16 @@
+CHECK: define void @call_a_bunch_of_functions({{.*}} {
+
+# Make sure that indirect call promotion inserted a check against the most
+# frequently called function.
+CHECK: %{{.*}} = icmp eq {{void \(\)\*|ptr}} %{{.*}}, @function_called_always
+
+# Check that the call to `function_called_always` was inlined, so that we
+# directly call `opaque_f1` from the upstream crate.
+CHECK: call void @opaque_f1()
+
+
+# Same checks as above, repeated for the trait object case
+
+CHECK: define void @call_a_bunch_of_trait_methods({{.*}}
+CHECK: %{{.*}} = icmp eq {{void \(\{\}\*\)\*|ptr}} %{{.*}}, {{.*}}@foo
+CHECK: tail call void @opaque_f2()
diff --git a/tests/run-make/pgo-indirect-call-promotion/interesting.rs b/tests/run-make/pgo-indirect-call-promotion/interesting.rs
new file mode 100644
index 000000000..4fd096d62
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/interesting.rs
@@ -0,0 +1,56 @@
+#![crate_name="interesting"]
+#![crate_type="rlib"]
+
+extern crate opaque;
+
+#[no_mangle]
+pub fn function_called_always() {
+ opaque::opaque_f1();
+}
+
+#[no_mangle]
+pub fn function_called_never() {
+ opaque::opaque_f2();
+}
+
+#[no_mangle]
+pub fn call_a_bunch_of_functions(fns: &[fn()]) {
+
+ // Indirect call promotion transforms the below into something like
+ //
+ // for f in fns {
+ // if f == function_called_always {
+ // function_called_always()
+ // } else {
+ // f();
+ // }
+ // }
+ //
+ // where `function_called_always` actually gets inlined too.
+
+ for f in fns {
+ f();
+ }
+}
+
+
+pub trait Foo {
+ fn foo(&self);
+}
+
+impl Foo for u32 {
+
+ #[no_mangle]
+ fn foo(&self) {
+ opaque::opaque_f2();
+ }
+}
+
+#[no_mangle]
+pub fn call_a_bunch_of_trait_methods(trait_objects: &[&dyn Foo]) {
+
+ // Same as above, just with vtables in between
+ for x in trait_objects {
+ x.foo();
+ }
+}
diff --git a/tests/run-make/pgo-indirect-call-promotion/main.rs b/tests/run-make/pgo-indirect-call-promotion/main.rs
new file mode 100644
index 000000000..27181f307
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/main.rs
@@ -0,0 +1,14 @@
+extern crate interesting;
+
+fn main() {
+ // function pointer case
+ let fns: Vec<_> = std::iter::repeat(interesting::function_called_always as fn())
+ .take(1000)
+ .collect();
+ interesting::call_a_bunch_of_functions(&fns[..]);
+
+ // Trait object case
+ let trait_objects = vec![0u32; 1000];
+ let trait_objects: Vec<_> = trait_objects.iter().map(|x| x as &dyn interesting::Foo).collect();
+ interesting::call_a_bunch_of_trait_methods(&trait_objects[..]);
+}
diff --git a/tests/run-make/pgo-indirect-call-promotion/opaque.rs b/tests/run-make/pgo-indirect-call-promotion/opaque.rs
new file mode 100644
index 000000000..9628d711c
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/opaque.rs
@@ -0,0 +1,7 @@
+#![crate_name="opaque"]
+#![crate_type="rlib"]
+
+#[no_mangle]
+pub fn opaque_f1() {}
+#[no_mangle]
+pub fn opaque_f2() {}