summaryrefslogtreecommitdiffstats
path: root/tests/run-make/pgo-branch-weights
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make/pgo-branch-weights')
-rw-r--r--tests/run-make/pgo-branch-weights/Makefile34
-rw-r--r--tests/run-make/pgo-branch-weights/filecheck-patterns.txt24
-rw-r--r--tests/run-make/pgo-branch-weights/interesting.rs40
-rw-r--r--tests/run-make/pgo-branch-weights/main.rs17
-rw-r--r--tests/run-make/pgo-branch-weights/opaque.rs6
5 files changed, 121 insertions, 0 deletions
diff --git a/tests/run-make/pgo-branch-weights/Makefile b/tests/run-make/pgo-branch-weights/Makefile
new file mode 100644
index 000000000..c60206a1f
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/Makefile
@@ -0,0 +1,34 @@
+# 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
+
+# For some very small programs GNU ld seems to not properly handle
+# instrumentation sections correctly. Neither Gold nor LLD have that problem.
+ifeq ($(UNAME),Linux)
+ifneq (,$(findstring x86,$(TARGET)))
+COMMON_FLAGS=-Clink-args=-fuse-ld=gold
+endif
+endif
+
+
+all:
+ # We don't compile `opaque` with either optimizations or instrumentation.
+ $(RUSTC) $(COMMON_FLAGS) opaque.rs || exit 1
+ # Compile the test program with instrumentation
+ mkdir -p "$(TMPDIR)/prof_data_dir" || exit 1
+ $(RUSTC) $(COMMON_FLAGS) interesting.rs \
+ -Cprofile-generate="$(TMPDIR)/prof_data_dir" -O -Ccodegen-units=1 || exit 1
+ $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)/prof_data_dir" -O || exit 1
+ # The argument below generates to the expected branch weights
+ $(call RUN,main aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc) || exit 1
+ "$(LLVM_BIN_DIR)/llvm-profdata" merge \
+ -o "$(TMPDIR)/prof_data_dir/merged.profdata" \
+ "$(TMPDIR)/prof_data_dir" || exit 1
+ $(RUSTC) $(COMMON_FLAGS) interesting.rs \
+ -Cprofile-use="$(TMPDIR)/prof_data_dir/merged.profdata" -O \
+ -Ccodegen-units=1 --emit=llvm-ir || exit 1
+ cat "$(TMPDIR)/interesting.ll" | "$(LLVM_FILECHECK)" filecheck-patterns.txt
diff --git a/tests/run-make/pgo-branch-weights/filecheck-patterns.txt b/tests/run-make/pgo-branch-weights/filecheck-patterns.txt
new file mode 100644
index 000000000..70d5a645c
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/filecheck-patterns.txt
@@ -0,0 +1,24 @@
+
+# First, establish that certain !prof labels are attached to the expected
+# functions and branching instructions.
+
+CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] {
+CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !prof [[branch_weights0:![0-9]+]]
+
+CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] {
+CHECK: switch i32 %c, label {{.*}} [
+CHECK-NEXT: i32 97, label {{.*}}
+CHECK-NEXT: i32 98, label {{.*}}
+CHECK-NEXT: ], !prof [[branch_weights1:![0-9]+]]
+
+CHECK: define void @function_called_never(i32 {{.*}} !prof [[function_called_never_id:![0-9]+]] {
+
+
+
+# Now check that those !prof tags hold the expected counts
+
+CHECK: [[function_called_twice_id]] = !{!"function_entry_count", i64 2}
+CHECK: [[branch_weights0]] = !{!"branch_weights", i32 2, i32 0}
+CHECK: [[function_called_42_times_id]] = !{!"function_entry_count", i64 42}
+CHECK: [[branch_weights1]] = !{!"branch_weights", i32 2, i32 12, i32 28}
+CHECK: [[function_called_never_id]] = !{!"function_entry_count", i64 0}
diff --git a/tests/run-make/pgo-branch-weights/interesting.rs b/tests/run-make/pgo-branch-weights/interesting.rs
new file mode 100644
index 000000000..a26d6fd69
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/interesting.rs
@@ -0,0 +1,40 @@
+#![crate_name="interesting"]
+#![crate_type="rlib"]
+
+extern crate opaque;
+
+#[no_mangle]
+#[inline(never)]
+pub fn function_called_twice(c: char) {
+ if c == '2' {
+ // This branch is taken twice
+ opaque::f1();
+ } else {
+ // This branch is never taken
+ opaque::f2();
+ }
+}
+
+#[no_mangle]
+#[inline(never)]
+pub fn function_called_42_times(c: char) {
+ if c == 'a' {
+ // This branch is taken 12 times
+ opaque::f1();
+ } else {
+
+ if c == 'b' {
+ // This branch is taken 28 times
+ opaque::f2();
+ } else {
+ // This branch is taken 2 times
+ opaque::f3();
+ }
+ }
+}
+
+#[no_mangle]
+#[inline(never)]
+pub fn function_called_never(_: char) {
+ opaque::f1();
+}
diff --git a/tests/run-make/pgo-branch-weights/main.rs b/tests/run-make/pgo-branch-weights/main.rs
new file mode 100644
index 000000000..619cf9c69
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/main.rs
@@ -0,0 +1,17 @@
+extern crate interesting;
+
+fn main() {
+ let arg = std::env::args().skip(1).next().unwrap();
+
+ for c in arg.chars() {
+ if c == '2' {
+ interesting::function_called_twice(c);
+ } else {
+ interesting::function_called_42_times(c);
+ }
+
+ if c == '0' {
+ interesting::function_called_never(c);
+ }
+ }
+}
diff --git a/tests/run-make/pgo-branch-weights/opaque.rs b/tests/run-make/pgo-branch-weights/opaque.rs
new file mode 100644
index 000000000..72f93c9fe
--- /dev/null
+++ b/tests/run-make/pgo-branch-weights/opaque.rs
@@ -0,0 +1,6 @@
+#![crate_name="opaque"]
+#![crate_type="rlib"]
+
+pub fn f1() {}
+pub fn f2() {}
+pub fn f3() {}