[compiler-rt] [compiler-rt][pgo] Add profile instrumentation test for coroutines (PR #213801)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 3 16:57:19 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-pgo

Author: Jin Huang (jinhuang1102)

<details>
<summary>Changes</summary>

This PR adds a compiler-rt test (`instrprof-coroutine-profile.cpp`) to verify PGO profile counter generation and ingestion for C++20 coroutines.

During investigating the iFDO profile ingested for coroutine pass, we found that the profile data contains entry counts for the original coroutine function (`foo`), but lacks the entry counters for the split `foo.resume` function. 

After inspecting [PassBuilderPipelines.cpp](https://github.com/llvm/llvm-project/blob/f7b7ec8d5542dcede1ae607aa74dfe36d7a3c530/llvm/lib/Passes/PassBuilderPipelines.cpp#L1273) confirms that `PGOInstrumentationGen` runs before `CoroSplitPass`. Therefore, 
- 1) the iFDO profile correctly ingests and associates profile counters with coroutine function `foo`. 
- 2) Separate function entry counters for `foo.resume` are not expected in the iFDO profile.

Added `compiler-rt/test/profile/instrprof-coroutine-profile.cpp` and use `llvm-profdata show` verify coroutine profile data. The IR dump after `PGOInstrumentationGen` confirms that the function entry count is tracking by counter[6] in the 8-element counter for `foo`.

```llvm
coro.alloc:                                       ; preds = %entry
  call void @<!-- -->llvm.instrprof.increment(ptr @<!-- -->__profn__Z3fooi, i64 650973721613012168, i32 8, i32 6)
  %2 = call i64 @<!-- -->llvm.coro.size.i64()
  %call = call noalias noundef nonnull ptr @<!-- -->_Znwm(i64 noundef %2) #<!-- -->14
  br label %coro.init

coro.init:                                        ; preds = %coro.alloc, %entry
```

---
Full diff: https://github.com/llvm/llvm-project/pull/213801.diff


1 Files Affected:

- (added) compiler-rt/test/profile/instrprof-coroutine-profile.cpp (+43) 


``````````diff
diff --git a/compiler-rt/test/profile/instrprof-coroutine-profile.cpp b/compiler-rt/test/profile/instrprof-coroutine-profile.cpp
new file mode 100644
index 0000000000000..a7037caafa68e
--- /dev/null
+++ b/compiler-rt/test/profile/instrprof-coroutine-profile.cpp
@@ -0,0 +1,43 @@
+// RUN: %clangxx_pgogen -std=c++20 -O2 -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata show -function=_Z3fooi -counts %t.profraw | FileCheck %s
+
+#include <coroutine>
+
+struct State {
+  struct promise_type {
+    std::suspend_never initial_suspend() noexcept { return {}; }
+    std::suspend_never final_suspend() noexcept { return {}; }
+    State get_return_object() noexcept {
+      return State{std::coroutine_handle<promise_type>::from_promise(*this)};
+    }
+    void return_void() noexcept {}
+    void unhandled_exception() noexcept {}
+  };
+  std::coroutine_handle<promise_type> handle;
+};
+
+struct Awaitable {
+  bool await_ready() noexcept { return false; }
+  void await_suspend(std::coroutine_handle<> h) noexcept { h.resume(); }
+  void await_resume() noexcept {}
+};
+
+__attribute__((noinline)) State foo(int x) {
+  for (int i = 0; i < x; ++i) {
+    co_await Awaitable{};
+  }
+  co_return;
+}
+
+int main() {
+  foo(5);
+  return 0;
+}
+
+// Note: Index 6 in Block counts (the 7th value '1') represents the function entry count of foo(5).
+// CHECK: Counters:
+// CHECK-NEXT:  _Z3fooi:
+// CHECK-NEXT:    Hash: {{.*}}
+// CHECK-NEXT:    Counters: 8
+// CHECK-NEXT:    Block counts: [{{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, {{[0-9]+}}, 1, {{[0-9]+}}]
\ No newline at end of file

``````````

</details>


https://github.com/llvm/llvm-project/pull/213801


More information about the llvm-commits mailing list