wlei b1a45c62f0 [llvm-profgen] Ignore branch count against outline function
For some transformations like hot-cold split or coro split, it can outline its part of function ranges. Since sample loader is the early stage of backend and no split happens at that time, compiler can't recognize those function, so in llvm-profgen we should attribute the sample to the original function. This is already done for the body range samples since we use the symbols from dwarf which is created before the split.

But for branch samples, the call from master function to its outlined function is actually not a call to the original function, we shouldn't add head/callsie samples for it. So instead of dwarf symbol, we use the symbols from symbol table and ignore those functions with special suffixes(like `.cold` ,`.resume`) for accumulating the callsite/head samples.

Reviewed By: hoy, wenlei

Differential Revision: https://reviews.llvm.org/D110864
2021-10-07 14:03:34 -07:00

84 lines
2.3 KiB
Plaintext

; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/coroutine.perfscript --binary=%S/Inputs/coroutine.perfbin --output=%t
; RUN: FileCheck %s --input-file %t --check-prefix=CHECK
; Check that the head sample count for ticker is 0.
; CHECK: _Z6tickeri:353:0
; CHECK-NOT: _Z6tickeri.resume
/*
* Inputs/coroutine.perfbin is generated by compiling the following source code:
* clang++ coroutine.cpp -std=c++2a -g2 -o coroutine
*/
#include <cstdint>
#include <cstdlib>
#include <ctime>
#include <experimental/coroutine>
#include <iostream>
struct task {
struct promise_type {
task get_return_object() { return {}; }
std::experimental::suspend_never initial_suspend() { return {}; }
std::experimental::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
};
template <typename T>
struct generator {
struct promise_type;
using handle = std::experimental::coroutine_handle<promise_type>;
struct promise_type {
int current_value;
static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }
auto get_return_object() { return generator{handle::from_promise(*this)}; }
auto initial_suspend() { return std::experimental::suspend_always{}; }
auto final_suspend() { return std::experimental::suspend_always{}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
auto yield_value(int value) {
current_value = value;
return std::experimental::suspend_always{};
}
};
bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }
int current_value() { return coro.promise().current_value; }
generator(generator const &) = delete;
generator(generator &&rhs) : coro(rhs.coro) { rhs.coro = nullptr; }
~generator() {
if (coro)
coro.destroy();
}
private:
generator(handle h) : coro(h) {}
handle coro;
};
generator<int> ticker(int count) {
for (int i = 0; i < count; ++i) {
srand(time(NULL));
uint32_t a = rand() % 10 + 1;
uint32_t b = rand() % 10 + 1;
uint64_t c = 0;
for (int i = 0; i < 1500; ++i) {
c = ((uint64_t)a) + b;
a = b;
b = c % 2147483648ULL;
}
co_yield a;
}
}
int main() {
auto g = ticker(500000);
uint64_t ans = 0;
while (g.move_next()) {
ans += g.current_value();
}
std::cout << ans << "\n";
}