BATCH 4 | Clone-Prune Analysis Code Pass On Both Architectures
Clone-Prune Analysis Code Pass On Both Architectures
Pass Works On x86_64 and aarch64 Architectures
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "basic-block.h"
#include "function.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "tree-pass.h"
#include "context.h"
#include <string.h>
#include <unordered_map>
#include <string>
#include <cstdio>
namespace {
const pass_data count_pass_data = {
GIMPLE_PASS,
"count",
OPTGROUP_NONE,
TV_NONE,
PROP_gimple_any,
0, 0, 0, 0
};
struct clone_signature {
int bb_count;
int gimple_count;
};
static std::unordered_map<std::string, clone_signature> clone_map;
bool is_internal_function(const char *name) {
return (strstr(name, "<anonymous>") || strstr(name, "tree_") ||
strstr(name, "va_gc::") || strstr(name, "pass_") ||
strstr(name, "optimize_") || strstr(name, "dump_"));
}
bool is_user_function(const char *name) {
return (strstr(name, "scale_samples") || strstr(name, "prune") || strstr(name, "noprune"));
}
class count_pass : public gimple_opt_pass {
public:
count_pass(gcc::context *ctxt) : gimple_opt_pass(count_pass_data, ctxt) {}
bool gate(function *fun) override {
(void)fun;
return true;
}
unsigned int execute(function *fun) override {
const char *full_name = function_name(fun);
if (!full_name) return 0;
if (is_internal_function(full_name)) return 0;
if (!is_user_function(full_name)) return 0;
char base_name[256] = "";
const char *dot = strchr(full_name, '.');
if (dot) {
size_t len = dot - full_name;
if (len >= sizeof(base_name)) len = sizeof(base_name) - 1;
strncpy(base_name, full_name, len);
base_name[len] = '\0';
} else {
strncpy(base_name, full_name, sizeof(base_name) - 1);
base_name[sizeof(base_name) - 1] = '\0';
}
int bb_count = 0, gimple_count = 0;
basic_block bb;
FOR_ALL_BB_FN(bb, fun) {
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
gimple_count++;
bb_count++;
}
bool is_resolver = strstr(full_name, "resolver") != nullptr;
if (!is_resolver) {
std::string base_str(base_name);
auto it = clone_map.find(base_str);
if (it == clone_map.end()) {
clone_map[base_str] = {bb_count, gimple_count};
} else {
const clone_signature &stored = it->second;
const char *result = (stored.bb_count == bb_count && stored.gimple_count == gimple_count)
? "PRUNE" : "NOPRUNE";
if (dump_file)
fprintf(dump_file, "%s: %s\n", result, base_name);
else
fprintf(stderr, "%s: %s\n", result, base_name);
clone_map.erase(it);
}
}
char filename[256];
snprintf(filename, sizeof(filename), "%s.count", full_name);
FILE *f = fopen(filename, "w");
if (f) {
fprintf(f, "Function: %s\n", full_name);
fprintf(f, "Basic Blocks: %d\n", bb_count);
fprintf(f, "GIMPLE Statements: %d\n", gimple_count);
fclose(f);
} else {
if (dump_file)
fprintf(dump_file, "Failed to write to %s\n", filename);
else
fprintf(stderr, "Failed to write to %s\n", filename);
}
if (dump_file)
fprintf(dump_file, "Function %s: %d BBs, %d GIMPLE stmts\n",
full_name, bb_count, gimple_count);
else
fprintf(stderr, "Function %s: %d BBs, %d GIMPLE stmts\n",
full_name, bb_count, gimple_count);
return 0;
}
};
}
opt_pass *make_count_pass(gcc::context *ctxt) {
return new count_pass(ctxt);
}
Comments
Post a Comment