about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2019-11-22 13:38:28 +0100
committerMichael Woerister <michaelwoerister@posteo>2019-11-22 13:52:55 +0100
commit68785d961459d3aa13ffa540471cdffe628d07f8 (patch)
treebd341b454491752004932f7974477fef35cebfd5
parent0675d65093e7173be676c07582085bf596ce966e (diff)
downloadrust-68785d961459d3aa13ffa540471cdffe628d07f8.tar.gz
rust-68785d961459d3aa13ffa540471cdffe628d07f8.zip
PGO: Add regression test for indirect call promotion.
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile36
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt16
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs56
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs14
-rw-r--r--src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs7
5 files changed, 129 insertions, 0 deletions
diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile
new file mode 100644
index 00000000000..e61018752c3
--- /dev/null
+++ b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/Makefile
@@ -0,0 +1,36 @@
+# needs-profiler-support
+
+-include ../tools.mk
+
+# This test makes sure that indirect call promotion is performed. The test
+# programs calls the same function a thousand times through a function pointer.
+# Only PGO data provides the information that it actually always is the same
+# function. We verify that the indirect call promotion pass inserts a check
+# whether it can make a direct call instead of the indirect call.
+
+# LLVM doesn't support instrumenting binaries that use SEH:
+# https://github.com/rust-lang/rust/issues/61002
+#
+# Things work fine with -Cpanic=abort though.
+ifdef IS_MSVC
+COMMON_FLAGS=-Cpanic=abort
+endif
+
+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/src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/filecheck-patterns.txt
new file mode 100644
index 00000000000..934159207e2
--- /dev/null
+++ b/src/test/run-make-fulldeps/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 ()* %{{.*}}, @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 ({}*)* %{{.*}}, {{.*}} @foo
+CHECK: tail call void @opaque_f2()
diff --git a/src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/interesting.rs
new file mode 100644
index 00000000000..4fd096d626d
--- /dev/null
+++ b/src/test/run-make-fulldeps/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/src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/main.rs
new file mode 100644
index 00000000000..27181f30710
--- /dev/null
+++ b/src/test/run-make-fulldeps/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/src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs b/src/test/run-make-fulldeps/pgo-indirect-call-promotion/opaque.rs
new file mode 100644
index 00000000000..9628d711c50
--- /dev/null
+++ b/src/test/run-make-fulldeps/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() {}