21 #include <gtest/gtest.h>
25 std::string
env(
const char* n) {
const char* v = getenv(n);
return v ? v :
""; }
26 std::string
cctlib_root() { std::string r =
env(
"CCTLIB_ROOT");
return r.empty() ?
"../.." : r; }
29 int run_pin(
const std::string& tool,
const std::vector<std::string>& args) {
30 std::string pin =
pin_root() +
"/pin";
31 std::vector<char*> argv;
32 argv.push_back(
const_cast<char*
>(pin.c_str()));
33 argv.push_back(
const_cast<char*
>(
"-t"));
34 argv.push_back(
const_cast<char*
>(tool.c_str()));
35 argv.push_back(
const_cast<char*
>(
"--"));
36 for (
auto&
a : args) argv.push_back(
const_cast<char*
>(
a.c_str()));
37 argv.push_back(
nullptr);
39 if (pid < 0)
return -1;
41 if (!
env(
"CCTLIB_TEST_VERBOSE").size()) {
42 int devnull = open(
"/dev/null", O_WRONLY);
43 if (devnull >= 0) { dup2(devnull, 1); dup2(devnull, 2); close(devnull); }
45 execv(pin.c_str(), argv.data());
49 if (waitpid(pid, &
status, 0) < 0)
return -1;
54 std::string
find_newest(
const std::string& dir,
const std::string& prefix) {
55 std::string cmd =
"ls -t " + dir +
"/" + prefix +
"* 2>/dev/null | head -1";
56 FILE* p = popen(cmd.c_str(),
"r");
58 char buf[4096]; std::string out;
59 if (fgets(
buf,
sizeof(
buf), p)) out =
buf;
61 if (!out.empty() && out.back() ==
'\n') out.pop_back();
65 std::ifstream in(path); std::stringstream ss; ss << in.rdbuf();
return ss.str();
67 void cleanup(
const std::string& dir,
const std::string& prefix) {
68 std::string cmd =
"rm -f " + dir +
"/" + prefix +
"*"; (void)system(cmd.c_str());
75 std::vector<double> bins;
76 std::regex header(R
"(TID \d+ instruction-reuse histo)");
78 if (!std::regex_search(content, m, header))
return bins;
79 std::string tail = content.substr(m.position() + m.length());
81 std::regex row(R
"(\s*(\d+)\s+([\d.]+e[+\-]\d+))");
82 auto begin = std::sregex_iterator(tail.begin(), tail.end(), row);
83 auto end = std::sregex_iterator();
84 for (
auto it = begin; it != end; ++it) {
85 size_t idx = std::stoul((*it)[1]);
86 double val = std::stod((*it)[2]);
87 if (bins.size() <= idx) bins.resize(idx + 1, 0.0);
90 if (bins.size() >= 32)
break;
101 tool_ = root_ +
"/clients/obj-intel64/ins_reuse_client.so";
102 ASSERT_EQ(0, access(tool_.c_str(), F_OK)) << tool_ <<
" missing";
103 ASSERT_EQ(0, chdir(root_.c_str())) <<
"chdir failed";
106 cleanup(root_,
"insReuse.out.");
107 int rc =
run_pin(tool_, {victim});
109 std::string out =
find_newest(root_,
"insReuse.out.");
110 EXPECT_FALSE(out.empty());
116 auto h = run_and_parse(
"/bin/ls");
118 for (
auto v :
h) total += (long)v;
131 auto h = run_and_parse(root_ +
"/tests/gtest/obj/apps/ins_reuse_tight_loop");
132 ASSERT_FALSE(
h.empty()) <<
"no histogram parsed";
133 double low = 0.0, mid = 0.0;
134 for (
size_t i = 0; i <
h.size(); ++i) {
135 if (i <= 4) low +=
h[i];
136 else if (i <= 12) mid +=
h[i];
139 <<
"low-bin mass=" << low <<
" mid-bin mass=" << mid;
142 for (
auto v :
h) total += v;
143 EXPECT_GT(total, 1e6);
150 auto h = run_and_parse(root_ +
"/tests/gtest/obj/apps/isa/ins_reuse_simd_loop");
151 ASSERT_FALSE(
h.empty()) <<
"no histogram parsed";
152 double low = 0.0, mid = 0.0;
153 for (
size_t i = 0; i <
h.size(); ++i) {
154 if (i <= 4) low +=
h[i];
155 else if (i <= 12) mid +=
h[i];
158 <<
"low-bin mass=" << low <<
" mid-bin mass=" << mid;
160 for (
auto v :
h) total += v;
161 EXPECT_GT(total, 1e6);
std::vector< double > run_and_parse(const std::string &victim)
static uint64_t buf[ITERS]
TEST_F(InsReuseIntegration, SimdLoopFillsLowBins)
std::vector< double > parse_histogram(const std::string &content)
std::string cctlib_root()
std::string read_file(const std::string &path)
std::string env(const char *n)
int run_pin(const std::string &tool, const std::vector< std::string > &args)
void cleanup(const std::string &dir, const std::string &prefix)
std::string find_newest(const std::string &dir, const std::string &prefix)