updated recc

This commit is contained in:
Anthony Pesch 2016-06-26 23:18:58 -07:00
parent 28650d1914
commit a68084ffa0
11 changed files with 171 additions and 183 deletions

View File

@ -247,7 +247,7 @@ endif()
#--------------------------------------------------
# tools
#--------------------------------------------------
set(RECC_SOURCES tools/recc.cc)
set(RECC_SOURCES tools/recc.c)
foreach(file ${REDREAM_SOURCES})
if(file MATCHES "(deps|src/(core|jit|sys))")

View File

@ -1,8 +1,10 @@
#ifndef X64_BACKEND_H
#define X64_BACKEND_H
struct jit_backend;
struct mem_interface;
#include "jit/backend/backend.h"
extern const struct register_def x64_registers[];
extern const int x64_num_registers;
struct jit_backend *x64_backend_create(const struct mem_interface *memif);
void x64_backend_destroy(struct jit_backend *b);

View File

@ -173,7 +173,7 @@ static inline bool ir_is_vector(enum ir_type type) {
return type == VALUE_V128;
}
bool ir_read(FILE *input, struct ir *ir);
int ir_read(FILE *input, struct ir *ir);
void ir_write(struct ir *ir, FILE *output);
struct ir_instr *ir_append_instr(struct ir *ir, enum ir_op op,

View File

@ -145,10 +145,10 @@ static void ir_lex_next(struct ir_parser *p) {
return;
}
bool ir_parse_type(struct ir_parser *p, struct ir *ir, enum ir_type *type) {
int ir_parse_type(struct ir_parser *p, struct ir *ir, enum ir_type *type) {
if (p->tok != TOK_TYPE) {
LOG_INFO("Unexpected token %d when parsing type", p->tok);
return false;
return 0;
}
// eat token
@ -156,13 +156,13 @@ bool ir_parse_type(struct ir_parser *p, struct ir *ir, enum ir_type *type) {
*type = p->val.ty;
return true;
return 1;
}
bool ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
int ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
if (p->tok != TOK_IDENTIFIER) {
LOG_INFO("Unexpected token %d when parsing op", p->tok);
return false;
return 0;
}
const char *op_str = p->val.s;
@ -177,7 +177,7 @@ bool ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
if (i == NUM_OPS) {
LOG_INFO("Unexpected op '%s'", op_str);
return false;
return 0;
}
// eat token
@ -185,15 +185,15 @@ bool ir_parse_op(struct ir_parser *p, struct ir *ir, enum ir_op *op) {
*op = (enum ir_op)i;
return true;
return 1;
}
bool ir_parse_value(struct ir_parser *p, struct ir *ir,
struct ir_value **value) {
int ir_parse_value(struct ir_parser *p, struct ir *ir,
struct ir_value **value) {
// parse value type
enum ir_type type;
if (!ir_parse_type(p, ir, &type)) {
return false;
return 0;
}
// parse value
@ -201,7 +201,7 @@ bool ir_parse_value(struct ir_parser *p, struct ir *ir,
const char *ident = p->val.s;
if (ident[0] != '%') {
return false;
return 0;
}
// lookup the slot slowly
@ -248,21 +248,21 @@ bool ir_parse_value(struct ir_parser *p, struct ir *ir,
break;
}
} else {
return false;
return 0;
}
// eat token
ir_lex_next(p);
return true;
return 1;
}
bool ir_parse_operator(struct ir_parser *p, struct ir *ir) {
int ir_parse_operator(struct ir_parser *p, struct ir *ir) {
const char *op_str = p->val.s;
if (strcmp(op_str, "=")) {
LOG_INFO("Unexpected operator '%s'", op_str);
return false;
return 0;
}
// eat token
@ -270,10 +270,10 @@ bool ir_parse_operator(struct ir_parser *p, struct ir *ir) {
// nothing to do, there's only one operator token
return true;
return 1;
}
bool ir_parse_instr(struct ir_parser *p, struct ir *ir) {
int ir_parse_instr(struct ir_parser *p, struct ir *ir) {
int slot = -1;
enum ir_type type = VALUE_V;
struct ir_value *arg[3] = {};
@ -281,31 +281,31 @@ bool ir_parse_instr(struct ir_parser *p, struct ir *ir) {
// parse result type and slot number
if (p->tok == TOK_TYPE) {
if (!ir_parse_type(p, ir, &type)) {
return false;
return 0;
}
const char *ident = p->val.s;
if (ident[0] != '%') {
return false;
return 0;
}
slot = atoi(&ident[1]);
ir_lex_next(p);
if (!ir_parse_operator(p, ir)) {
return false;
return 0;
}
}
// parse op
enum ir_op op;
if (!ir_parse_op(p, ir, &op)) {
return false;
return 0;
}
// parse arguments
for (int i = 0; i < 3; i++) {
if (!ir_parse_value(p, ir, &arg[i])) {
return false;
return 0;
}
if (p->tok != TOK_COMMA) {
@ -325,14 +325,14 @@ bool ir_parse_instr(struct ir_parser *p, struct ir *ir) {
instr->tag = slot;
return true;
return 1;
}
bool ir_read(FILE *input, struct ir *ir) {
int ir_read(FILE *input, struct ir *ir) {
struct ir_parser p = {};
p.input = input;
while (true) {
while (1) {
ir_lex_next(&p);
if (p.tok == TOK_EOF) {
@ -340,9 +340,9 @@ bool ir_read(FILE *input, struct ir *ir) {
}
if (!ir_parse_instr(&p, ir)) {
return false;
return 0;
}
}
return true;
return 1;
}

View File

@ -89,7 +89,7 @@ static void ir_write_instr(const struct ir_instr *instr, FILE *output) {
fprintf(output, " ");
// print each argument
bool need_comma = false;
int need_comma = 0;
for (int i = 0; i < 3; i++) {
const struct ir_value *arg = instr->arg[i];
@ -100,12 +100,12 @@ static void ir_write_instr(const struct ir_instr *instr, FILE *output) {
if (need_comma) {
fprintf(output, ", ");
need_comma = false;
need_comma = 0;
}
ir_write_value(arg, output);
need_comma = true;
need_comma = 1;
}
// fprintf(output, "[tag %" PRId64 ", reg %d]", instr->tag, instr->reg);

View File

@ -3,8 +3,6 @@
struct ir;
extern const char *cve_name;
void cve_run(struct ir *ir);
#endif

View File

@ -3,8 +3,6 @@
struct ir;
extern const char *dce_name;
void dce_run(struct ir *ir);
#endif

View File

@ -3,8 +3,6 @@
struct ir;
extern const char *lse_name;
void lse_run(struct ir *ir);
#endif

View File

@ -4,8 +4,6 @@
struct ir;
struct register_def;
extern const char *ra_name;
void ra_run(struct ir *ir, const struct register_def *registers,
int num_registers);

135
tools/recc.c Normal file
View File

@ -0,0 +1,135 @@
#include "core/log.h"
#include "core/option.h"
#include "jit/backend/x64/x64_backend.h"
#include "jit/frontend/sh4/sh4_frontend.h"
#include "jit/ir/ir.h"
#include "jit/ir/passes/conversion_elimination_pass.h"
#include "jit/ir/passes/dead_code_elimination_pass.h"
#include "jit/ir/passes/load_store_elimination_pass.h"
#include "jit/ir/passes/pass_stat.h"
#include "jit/ir/passes/register_allocation_pass.h"
#include "sys/filesystem.h"
DEFINE_OPTION_BOOL(help, false, "Show help");
DEFINE_OPTION_STRING(pass, "lse,cve,dce,ra",
"Comma-separated list of passes to run");
DEFINE_OPTION_BOOL(print_after_all, true, "Print IR after each pass");
DEFINE_OPTION_BOOL(stats, true, "Display pass stats");
DEFINE_STAT(num_instrs, "Total number of instructions");
DEFINE_STAT(num_instrs_removed, "Number of instructions removed");
static uint8_t ir_buffer[1024 * 1024];
static int get_num_instrs(const struct ir *ir) {
int n = 0;
list_for_each_entry(instr, &ir->instrs, struct ir_instr, it) {
((void)instr);
n++;
}
return n;
}
static void process_file(const char *filename, bool disable_ir_dump) {
struct ir ir = {};
ir.buffer = ir_buffer;
ir.capacity = sizeof(ir_buffer);
// read in the input ir
FILE *input = fopen(filename, "r");
CHECK(input);
int r = ir_read(input, &ir);
fclose(input);
CHECK(r);
int num_instrs_before = get_num_instrs(&ir);
// run optimization passes
char passes[MAX_OPTION_LENGTH];
strncpy(passes, OPTION_pass, sizeof(passes));
char *name = strtok(passes, ",");
while (name) {
if (!strcmp(name, "lse")) {
lse_run(&ir);
} else if (!strcmp(name, "cve")) {
cve_run(&ir);
} else if (!strcmp(name, "dce")) {
dce_run(&ir);
} else if (!strcmp(name, "ra")) {
ra_run(&ir, x64_registers, x64_num_registers);
} else {
LOG_WARNING("Unknown pass %s", name);
}
// print IR after each pass if requested
if (!disable_ir_dump && OPTION_print_after_all) {
LOG_INFO("===-----------------------------------------------------===");
LOG_INFO("IR after %s", name);
LOG_INFO("===-----------------------------------------------------===");
ir_write(&ir, stdout);
LOG_INFO("");
}
name = strtok(NULL, ",");
}
int num_instrs_after = get_num_instrs(&ir);
// print out the final IR
if (!disable_ir_dump && !OPTION_print_after_all) {
ir_write(&ir, stdout);
}
STAT_num_instrs += num_instrs_before;
STAT_num_instrs_removed += num_instrs_before - num_instrs_after;
}
static void process_dir(const char *path) {
DIR *dir = opendir(path);
if (dir) {
struct dirent *ent = readdir(dir);
while (ent) {
if (!(ent->d_type & DT_REG)) {
continue;
}
char filename[PATH_MAX];
snprintf(filename, sizeof(filename), "%s" PATH_SEPARATOR "%s", path,
ent->d_name);
LOG_INFO("processing %s", filename);
process_file(filename, true);
}
closedir(dir);
}
}
int main(int argc, char **argv) {
options_parse(&argc, &argv);
if (OPTION_help) {
options_print_help();
return EXIT_SUCCESS;
}
const char *path = argv[1];
if (fs_isfile(path)) {
process_file(path, false);
} else {
process_dir(path);
}
if (OPTION_stats) {
pass_stat_print_all();
}
return EXIT_SUCCESS;
}

View File

@ -1,141 +0,0 @@
#include <gflags/gflags.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include "jit/backend/x64/x64_backend.h"
#include "jit/frontend/sh4/sh4_frontend.h"
#include "jit/ir/ir_builder.h"
#include "jit/ir/ir_reader.h"
#include "jit/ir/passes/conversion_elimination_pass.h"
#include "jit/ir/passes/dead_code_elimination_pass.h"
#include "jit/ir/passes/load_store_elimination_pass.h"
#include "jit/ir/passes/register_allocation_pass.h"
#include "sys/filesystem.h"
using namespace re;
using namespace re::jit::backend;
using namespace re::jit::backend::x64;
using namespace re::jit::ir;
using namespace re::jit::ir::passes;
using namespace re::sys;
DEFINE_string(pass, "lse,cve,dce,ra", "Comma-separated list of passes to run");
DEFINE_bool(print_after_all, true, "Print IR after each pass");
DEFINE_bool(stats, true, "Display pass stats");
DEFINE_STAT(num_instrs, "Total number of instructions");
DEFINE_STAT(num_instrs_removed, "Number of instructions removed");
static std::vector<std::string> split(const std::string &s, char delim) {
std::stringstream ss(s);
std::string item;
std::vector<std::string> elems;
while (std::getline(ss, item, delim)) {
elems.push_back(std::move(item));
}
return elems;
}
static int get_num_instrs(IRBuilder &builder) {
int n = 0;
for (auto instr : builder.instrs()) {
((void)instr);
n++;
}
return n;
}
static void process_file(const char *filename, bool disable_ir_dump) {
Arena arena(4096);
IRBuilder builder(arena);
// read in the input ir
IRReader reader;
std::ifstream input_stream(filename);
CHECK(reader.Parse(input_stream, builder));
int num_instrs_before = get_num_instrs(builder);
// run optimization passes
std::vector<std::string> passes = split(FLAGS_pass, ',');
for (auto name : passes) {
std::unique_ptr<Pass> pass;
if (name == LoadStoreEliminationPass::NAME) {
pass = std::unique_ptr<Pass>(new LoadStoreEliminationPass());
} else if (name == ConversionEliminationPass::NAME) {
pass = std::unique_ptr<Pass>(new ConversionEliminationPass());
} else if (name == DeadCodeEliminationPass::NAME) {
pass = std::unique_ptr<Pass>(new DeadCodeEliminationPass());
} else if (name == RegisterAllocationPass::NAME) {
pass = std::unique_ptr<Pass>(
new RegisterAllocationPass(x64_registers, x64_num_registers));
} else {
LOG_WARNING("Unknown pass %s", name.c_str());
}
pass->Run(builder);
// print IR after each pass if requested
if (!disable_ir_dump && FLAGS_print_after_all) {
LOG_INFO("===-----------------------------------------------------===");
LOG_INFO("IR after %s", pass->name());
LOG_INFO("===-----------------------------------------------------===");
builder.Dump();
LOG_INFO("");
}
}
int num_instrs_after = get_num_instrs(builder);
// print out the final IR
if (!disable_ir_dump && !FLAGS_print_after_all) {
builder.Dump();
LOG_INFO("");
}
num_instrs += num_instrs_before;
num_instrs_removed += num_instrs_before - num_instrs_after;
}
static void process_dir(const char *path) {
if (DIR *dir = opendir(path)) {
while (struct dirent *ent = readdir(dir)) {
if (!(ent->d_type & DT_REG)) {
continue;
}
char filename[PATH_MAX];
snprintf(filename, sizeof(filename), "%s" PATH_SEPARATOR "%s", path,
ent->d_name);
LOG_INFO("processing %s", filename);
process_file(filename, true);
}
closedir(dir);
}
}
int main(int argc, char **argv) {
google::ParseCommandLineFlags(&argc, &argv, true);
const char *path = argv[1];
if (IsFile(path)) {
process_file(path, false);
} else {
process_dir(path);
}
if (FLAGS_stats) {
DumpStats();
}
google::ShutDownCommandLineFlags();
return 0;
}