mirror of https://github.com/inolen/redream.git
added frontend code size stats to recc
This commit is contained in:
parent
3cb36fc6c4
commit
162bfce38f
|
@ -1609,6 +1609,8 @@ EMITTER(CALL_FALLBACK) {
|
||||||
e.call(fallback);
|
e.call(fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EMITTER(DEBUG_INFO) {}
|
||||||
|
|
||||||
void x64_backend_destroy(struct jit_backend *jit_backend) {
|
void x64_backend_destroy(struct jit_backend *jit_backend) {
|
||||||
struct x64_backend *backend = (struct x64_backend *)jit_backend;
|
struct x64_backend *backend = (struct x64_backend *)jit_backend;
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,9 @@ static void ir_branch_true_guest(struct sh4_frontend *frontend, struct ir *ir,
|
||||||
void sh4_emit_instr(struct sh4_frontend *frontend, struct ir *ir, int flags,
|
void sh4_emit_instr(struct sh4_frontend *frontend, struct ir *ir, int flags,
|
||||||
const struct sh4_instr *instr,
|
const struct sh4_instr *instr,
|
||||||
const struct sh4_instr *delay) {
|
const struct sh4_instr *delay) {
|
||||||
|
/* emit debug info op for recc metrics */
|
||||||
|
ir_debug_info(ir, instr->addr, ir_alloc_i16(ir, instr->opcode));
|
||||||
|
|
||||||
(emit_callbacks[instr->op])(frontend, ir, flags, instr, delay);
|
(emit_callbacks[instr->op])(frontend, ir, flags, instr, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ static struct ir_instr *ir_alloc_instr(struct ir *ir, enum ir_op op) {
|
||||||
|
|
||||||
instr->op = op;
|
instr->op = op;
|
||||||
|
|
||||||
// initialize use links
|
/* initialize use links */
|
||||||
for (int i = 0; i < MAX_INSTR_ARGS; i++) {
|
for (int i = 0; i < MAX_INSTR_ARGS; i++) {
|
||||||
struct ir_use *use = &instr->used[i];
|
struct ir_use *use = &instr->used[i];
|
||||||
use->instr = instr;
|
use->instr = instr;
|
||||||
|
@ -43,7 +43,7 @@ struct ir_instr *ir_append_instr(struct ir *ir, enum ir_op op,
|
||||||
enum ir_type result_type) {
|
enum ir_type result_type) {
|
||||||
struct ir_instr *instr = ir_alloc_instr(ir, op);
|
struct ir_instr *instr = ir_alloc_instr(ir, op);
|
||||||
|
|
||||||
// allocate result if needed
|
/* allocate result if needed */
|
||||||
if (result_type != VALUE_V) {
|
if (result_type != VALUE_V) {
|
||||||
struct ir_value *result = ir_calloc(ir, sizeof(struct ir_value));
|
struct ir_value *result = ir_calloc(ir, sizeof(struct ir_value));
|
||||||
result->type = result_type;
|
result->type = result_type;
|
||||||
|
@ -60,7 +60,7 @@ struct ir_instr *ir_append_instr(struct ir *ir, enum ir_op op,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ir_remove_instr(struct ir *ir, struct ir_instr *instr) {
|
void ir_remove_instr(struct ir *ir, struct ir_instr *instr) {
|
||||||
// remove arguments from the use lists of their values
|
/* remove arguments from the use lists of their values */
|
||||||
for (int i = 0; i < MAX_INSTR_ARGS; i++) {
|
for (int i = 0; i < MAX_INSTR_ARGS; i++) {
|
||||||
struct ir_value *value = instr->arg[i];
|
struct ir_value *value = instr->arg[i];
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ struct ir_value *ir_alloc_label(struct ir *ir, const char *format, ...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ir_local *ir_alloc_local(struct ir *ir, enum ir_type type) {
|
struct ir_local *ir_alloc_local(struct ir *ir, enum ir_type type) {
|
||||||
// align local to natural size
|
/* align local to natural size */
|
||||||
int type_size = ir_type_size(type);
|
int type_size = ir_type_size(type);
|
||||||
ir->locals_size = align_up(ir->locals_size, type_size);
|
ir->locals_size = align_up(ir->locals_size, type_size);
|
||||||
|
|
||||||
|
@ -218,8 +218,8 @@ void ir_replace_use(struct ir_use *use, struct ir_value *other) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace all uses of v with other
|
|
||||||
void ir_replace_uses(struct ir_value *v, struct ir_value *other) {
|
void ir_replace_uses(struct ir_value *v, struct ir_value *other) {
|
||||||
|
/* replace all uses of v with other */
|
||||||
CHECK_NE(v, other);
|
CHECK_NE(v, other);
|
||||||
|
|
||||||
list_for_each_entry_safe(use, &v->uses, struct ir_use, it) {
|
list_for_each_entry_safe(use, &v->uses, struct ir_use, it) {
|
||||||
|
@ -825,3 +825,9 @@ void ir_call_fallback(struct ir *ir, void *fallback, uint32_t addr,
|
||||||
ir_set_arg1(ir, instr, ir_alloc_i32(ir, addr));
|
ir_set_arg1(ir, instr, ir_alloc_i32(ir, addr));
|
||||||
ir_set_arg2(ir, instr, ir_alloc_i32(ir, raw_instr));
|
ir_set_arg2(ir, instr, ir_alloc_i32(ir, raw_instr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ir_debug_info(struct ir *ir, uint32_t addr, struct ir_value *data) {
|
||||||
|
struct ir_instr *instr = ir_append_instr(ir, OP_DEBUG_INFO, VALUE_V);
|
||||||
|
ir_set_arg0(ir, instr, ir_alloc_i32(ir, addr));
|
||||||
|
ir_set_arg1(ir, instr, data);
|
||||||
|
}
|
||||||
|
|
|
@ -41,16 +41,16 @@ enum ir_cmp {
|
||||||
struct ir_value;
|
struct ir_value;
|
||||||
struct ir_instr;
|
struct ir_instr;
|
||||||
|
|
||||||
// use is a layer of indirection between an instruction and the values it uses
|
/* use is a layer of indirection between an instruction and the values it uses
|
||||||
// as arguments. this indirection makes it possible to maintain a list for each
|
as arguments. this indirection makes it possible to maintain a list for each
|
||||||
// value of the arguments that reference it
|
value of the arguments that reference it */
|
||||||
struct ir_use {
|
struct ir_use {
|
||||||
// the instruction that's using the value
|
/* the instruction that's using the value */
|
||||||
struct ir_instr *instr;
|
struct ir_instr *instr;
|
||||||
|
|
||||||
// pointer to the argument that's using the value. this is used to substitute
|
/* pointer to the argument that's using the value. this is used to substitute
|
||||||
// a new value for the argument in the case that the original value is
|
a new value for the argument in the case that the original value is
|
||||||
// removed (e.g. due to constant propagation)
|
removed (e.g. due to constant propagation) */
|
||||||
struct ir_value **parg;
|
struct ir_value **parg;
|
||||||
|
|
||||||
struct list_node it;
|
struct list_node it;
|
||||||
|
@ -69,16 +69,16 @@ struct ir_value {
|
||||||
char *str;
|
char *str;
|
||||||
};
|
};
|
||||||
|
|
||||||
// instruction that defines this value (non-constant values)
|
/* instruction that defines this value (non-constant values) */
|
||||||
struct ir_instr *def;
|
struct ir_instr *def;
|
||||||
|
|
||||||
// instructions that use this value as an argument
|
/* instructions that use this value as an argument */
|
||||||
struct list uses;
|
struct list uses;
|
||||||
|
|
||||||
// host register allocated for this value
|
/* host register allocated for this value */
|
||||||
int reg;
|
int reg;
|
||||||
|
|
||||||
// generic meta data used by optimization passes
|
/* generic meta data used by optimization passes */
|
||||||
intptr_t tag;
|
intptr_t tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,24 +87,24 @@ struct ir_value {
|
||||||
struct ir_instr {
|
struct ir_instr {
|
||||||
enum ir_op op;
|
enum ir_op op;
|
||||||
|
|
||||||
// values used by each argument. note, the argument / use is split into two
|
/* values used by each argument. note, the argument / use is split into two
|
||||||
// separate members to ease reading the argument value (instr->arg[0] vs
|
separate members to ease reading the argument value (instr->arg[0] vs
|
||||||
// instr->arg[0].value)
|
instr->arg[0].value) */
|
||||||
struct ir_value *arg[MAX_INSTR_ARGS];
|
struct ir_value *arg[MAX_INSTR_ARGS];
|
||||||
struct ir_use used[MAX_INSTR_ARGS];
|
struct ir_use used[MAX_INSTR_ARGS];
|
||||||
|
|
||||||
// result of the instruction. note, instruction results don't consider
|
/* result of the instruction. note, instruction results don't consider
|
||||||
// themselves users of the value (eases register allocation logic)
|
themselves users of the value (eases register allocation logic) */
|
||||||
struct ir_value *result;
|
struct ir_value *result;
|
||||||
|
|
||||||
// generic meta data used by optimization passes
|
/* generic meta data used by optimization passes */
|
||||||
intptr_t tag;
|
intptr_t tag;
|
||||||
|
|
||||||
struct list_node it;
|
struct list_node it;
|
||||||
};
|
};
|
||||||
|
|
||||||
// locals are allocated for values that need to be spilled to the stack
|
/* locals are allocated for values that need to be spilled to the stack
|
||||||
// during register allocation
|
during register allocation */
|
||||||
struct ir_local {
|
struct ir_local {
|
||||||
enum ir_type type;
|
enum ir_type type;
|
||||||
struct ir_value *offset;
|
struct ir_value *offset;
|
||||||
|
@ -208,12 +208,12 @@ void ir_replace_uses(struct ir_value *v, struct ir_value *other);
|
||||||
|
|
||||||
uint64_t ir_zext_constant(const struct ir_value *v);
|
uint64_t ir_zext_constant(const struct ir_value *v);
|
||||||
|
|
||||||
// direct access to host memory
|
/* direct access to host memory */
|
||||||
struct ir_value *ir_load(struct ir *ir, struct ir_value *addr,
|
struct ir_value *ir_load(struct ir *ir, struct ir_value *addr,
|
||||||
enum ir_type type);
|
enum ir_type type);
|
||||||
void ir_store(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
void ir_store(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
||||||
|
|
||||||
// guest memory operations
|
/* guest memory operations */
|
||||||
struct ir_value *ir_load_fast(struct ir *ir, struct ir_value *addr,
|
struct ir_value *ir_load_fast(struct ir *ir, struct ir_value *addr,
|
||||||
enum ir_type type);
|
enum ir_type type);
|
||||||
void ir_store_fast(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
void ir_store_fast(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
||||||
|
@ -222,16 +222,16 @@ struct ir_value *ir_load_slow(struct ir *ir, struct ir_value *addr,
|
||||||
enum ir_type type);
|
enum ir_type type);
|
||||||
void ir_store_slow(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
void ir_store_slow(struct ir *ir, struct ir_value *addr, struct ir_value *v);
|
||||||
|
|
||||||
// context operations
|
/* context operations */
|
||||||
struct ir_value *ir_load_context(struct ir *ir, size_t offset,
|
struct ir_value *ir_load_context(struct ir *ir, size_t offset,
|
||||||
enum ir_type type);
|
enum ir_type type);
|
||||||
void ir_store_context(struct ir *ir, size_t offset, struct ir_value *v);
|
void ir_store_context(struct ir *ir, size_t offset, struct ir_value *v);
|
||||||
|
|
||||||
// local operations
|
/* local operations */
|
||||||
struct ir_value *ir_load_local(struct ir *ir, struct ir_local *local);
|
struct ir_value *ir_load_local(struct ir *ir, struct ir_local *local);
|
||||||
void ir_store_local(struct ir *ir, struct ir_local *local, struct ir_value *v);
|
void ir_store_local(struct ir *ir, struct ir_local *local, struct ir_value *v);
|
||||||
|
|
||||||
// cast / conversion operations
|
/* cast / conversion operations */
|
||||||
struct ir_value *ir_ftoi(struct ir *ir, struct ir_value *v,
|
struct ir_value *ir_ftoi(struct ir *ir, struct ir_value *v,
|
||||||
enum ir_type dest_type);
|
enum ir_type dest_type);
|
||||||
struct ir_value *ir_itof(struct ir *ir, struct ir_value *v,
|
struct ir_value *ir_itof(struct ir *ir, struct ir_value *v,
|
||||||
|
@ -247,7 +247,7 @@ struct ir_value *ir_fext(struct ir *ir, struct ir_value *v,
|
||||||
struct ir_value *ir_ftrunc(struct ir *ir, struct ir_value *v,
|
struct ir_value *ir_ftrunc(struct ir *ir, struct ir_value *v,
|
||||||
enum ir_type dest_type);
|
enum ir_type dest_type);
|
||||||
|
|
||||||
// conditionals
|
/* conditionals */
|
||||||
struct ir_value *ir_select(struct ir *ir, struct ir_value *cond,
|
struct ir_value *ir_select(struct ir *ir, struct ir_value *cond,
|
||||||
struct ir_value *t, struct ir_value *f);
|
struct ir_value *t, struct ir_value *f);
|
||||||
struct ir_value *ir_cmp_eq(struct ir *ir, struct ir_value *a,
|
struct ir_value *ir_cmp_eq(struct ir *ir, struct ir_value *a,
|
||||||
|
@ -283,7 +283,7 @@ struct ir_value *ir_fcmp_le(struct ir *ir, struct ir_value *a,
|
||||||
struct ir_value *ir_fcmp_lt(struct ir *ir, struct ir_value *a,
|
struct ir_value *ir_fcmp_lt(struct ir *ir, struct ir_value *a,
|
||||||
struct ir_value *b);
|
struct ir_value *b);
|
||||||
|
|
||||||
// integer math operators
|
/* integer math operators */
|
||||||
struct ir_value *ir_add(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_add(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_sub(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_sub(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_smul(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_smul(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
|
@ -292,7 +292,7 @@ struct ir_value *ir_div(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_neg(struct ir *ir, struct ir_value *a);
|
struct ir_value *ir_neg(struct ir *ir, struct ir_value *a);
|
||||||
struct ir_value *ir_abs(struct ir *ir, struct ir_value *a);
|
struct ir_value *ir_abs(struct ir *ir, struct ir_value *a);
|
||||||
|
|
||||||
// floating point math operators
|
/* floating point math operators */
|
||||||
struct ir_value *ir_fadd(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_fadd(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_fsub(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_fsub(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_fmul(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_fmul(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
|
@ -301,7 +301,7 @@ struct ir_value *ir_fneg(struct ir *ir, struct ir_value *a);
|
||||||
struct ir_value *ir_fabs(struct ir *ir, struct ir_value *a);
|
struct ir_value *ir_fabs(struct ir *ir, struct ir_value *a);
|
||||||
struct ir_value *ir_sqrt(struct ir *ir, struct ir_value *a);
|
struct ir_value *ir_sqrt(struct ir *ir, struct ir_value *a);
|
||||||
|
|
||||||
// vector math operators
|
/* vector math operators */
|
||||||
struct ir_value *ir_vbroadcast(struct ir *ir, struct ir_value *a);
|
struct ir_value *ir_vbroadcast(struct ir *ir, struct ir_value *a);
|
||||||
struct ir_value *ir_vadd(struct ir *ir, struct ir_value *a, struct ir_value *b,
|
struct ir_value *ir_vadd(struct ir *ir, struct ir_value *a, struct ir_value *b,
|
||||||
enum ir_type el_type);
|
enum ir_type el_type);
|
||||||
|
@ -310,7 +310,7 @@ struct ir_value *ir_vdot(struct ir *ir, struct ir_value *a, struct ir_value *b,
|
||||||
struct ir_value *ir_vmul(struct ir *ir, struct ir_value *a, struct ir_value *b,
|
struct ir_value *ir_vmul(struct ir *ir, struct ir_value *a, struct ir_value *b,
|
||||||
enum ir_type el_type);
|
enum ir_type el_type);
|
||||||
|
|
||||||
// bitwise operations
|
/* bitwise operations */
|
||||||
struct ir_value *ir_and(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_and(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_or(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_or(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
struct ir_value *ir_xor(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
struct ir_value *ir_xor(struct ir *ir, struct ir_value *a, struct ir_value *b);
|
||||||
|
@ -324,14 +324,14 @@ struct ir_value *ir_lshri(struct ir *ir, struct ir_value *a, int n);
|
||||||
struct ir_value *ir_ashd(struct ir *ir, struct ir_value *a, struct ir_value *n);
|
struct ir_value *ir_ashd(struct ir *ir, struct ir_value *a, struct ir_value *n);
|
||||||
struct ir_value *ir_lshd(struct ir *ir, struct ir_value *a, struct ir_value *n);
|
struct ir_value *ir_lshd(struct ir *ir, struct ir_value *a, struct ir_value *n);
|
||||||
|
|
||||||
// branches
|
/* branches */
|
||||||
void ir_label(struct ir *ir, struct ir_value *lbl);
|
void ir_label(struct ir *ir, struct ir_value *lbl);
|
||||||
void ir_branch(struct ir *ir, struct ir_value *dst);
|
void ir_branch(struct ir *ir, struct ir_value *dst);
|
||||||
void ir_branch_false(struct ir *ir, struct ir_value *cond,
|
void ir_branch_false(struct ir *ir, struct ir_value *cond,
|
||||||
struct ir_value *dst);
|
struct ir_value *dst);
|
||||||
void ir_branch_true(struct ir *ir, struct ir_value *cond, struct ir_value *dst);
|
void ir_branch_true(struct ir *ir, struct ir_value *cond, struct ir_value *dst);
|
||||||
|
|
||||||
// calls
|
/* calls */
|
||||||
void ir_call(struct ir *ir, struct ir_value *fn);
|
void ir_call(struct ir *ir, struct ir_value *fn);
|
||||||
void ir_call_1(struct ir *ir, struct ir_value *fn, struct ir_value *arg0);
|
void ir_call_1(struct ir *ir, struct ir_value *fn, struct ir_value *arg0);
|
||||||
void ir_call_2(struct ir *ir, struct ir_value *fn, struct ir_value *arg0,
|
void ir_call_2(struct ir *ir, struct ir_value *fn, struct ir_value *arg0,
|
||||||
|
@ -339,4 +339,7 @@ void ir_call_2(struct ir *ir, struct ir_value *fn, struct ir_value *arg0,
|
||||||
void ir_call_fallback(struct ir *ir, void *fallback, uint32_t addr,
|
void ir_call_fallback(struct ir *ir, void *fallback, uint32_t addr,
|
||||||
uint32_t raw_instr);
|
uint32_t raw_instr);
|
||||||
|
|
||||||
|
/* debug */
|
||||||
|
void ir_debug_info(struct ir *ir, uint32_t addr, struct ir_value *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -51,3 +51,4 @@ IR_OP(BRANCH_FALSE)
|
||||||
IR_OP(BRANCH_TRUE)
|
IR_OP(BRANCH_TRUE)
|
||||||
IR_OP(CALL)
|
IR_OP(CALL)
|
||||||
IR_OP(CALL_FALLBACK)
|
IR_OP(CALL_FALLBACK)
|
||||||
|
IR_OP(DEBUG_INFO)
|
||||||
|
|
|
@ -18,6 +18,7 @@ DEFINE_OPTION_STRING(pass, "lse,cve,esimp,dce,ra",
|
||||||
DEFINE_OPTION_INT(stats, 1, "Print pass stats");
|
DEFINE_OPTION_INT(stats, 1, "Print pass stats");
|
||||||
DEFINE_OPTION_INT(print_after_all, 1, "Print IR after each pass");
|
DEFINE_OPTION_INT(print_after_all, 1, "Print IR after each pass");
|
||||||
|
|
||||||
|
DEFINE_STAT(frontend_size, "Frontend code size");
|
||||||
DEFINE_STAT(backend_size, "Backend code size");
|
DEFINE_STAT(backend_size, "Backend code size");
|
||||||
DEFINE_STAT(num_instrs, "Total instructions");
|
DEFINE_STAT(num_instrs, "Total instructions");
|
||||||
DEFINE_STAT(num_instrs_removed, "Total instructions removed");
|
DEFINE_STAT(num_instrs_removed, "Total instructions removed");
|
||||||
|
@ -51,12 +52,20 @@ static void process_file(struct jit *jit, const char *filename,
|
||||||
fclose(input);
|
fclose(input);
|
||||||
CHECK(r);
|
CHECK(r);
|
||||||
|
|
||||||
int num_instrs_before = get_num_instrs(&ir);
|
/* calculate frontend input size */
|
||||||
|
list_for_each_entry(instr, &ir.instrs, struct ir_instr, it) {
|
||||||
|
if (instr->op == OP_DEBUG_INFO) {
|
||||||
|
struct ir_value *data = instr->arg[1];
|
||||||
|
STAT_frontend_size += ir_type_size(data->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* run optimization passes */
|
/* run optimization passes */
|
||||||
char passes[MAX_OPTION_LENGTH];
|
char passes[MAX_OPTION_LENGTH];
|
||||||
strncpy(passes, OPTION_pass, sizeof(passes));
|
strncpy(passes, OPTION_pass, sizeof(passes));
|
||||||
|
|
||||||
|
int num_instrs_before = get_num_instrs(&ir);
|
||||||
|
|
||||||
char *name = strtok(passes, ",");
|
char *name = strtok(passes, ",");
|
||||||
while (name) {
|
while (name) {
|
||||||
if (!strcmp(name, "lse")) {
|
if (!strcmp(name, "lse")) {
|
||||||
|
@ -85,12 +94,13 @@ static void process_file(struct jit *jit, const char *filename,
|
||||||
name = strtok(NULL, ",");
|
name = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int num_instrs_after = get_num_instrs(&ir);
|
||||||
|
|
||||||
/* print out the final ir */
|
/* print out the final ir */
|
||||||
if (!disable_ir_dump && !OPTION_print_after_all) {
|
if (!disable_ir_dump && !OPTION_print_after_all) {
|
||||||
ir_write(&ir, stdout);
|
ir_write(&ir, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_instrs_after = get_num_instrs(&ir);
|
|
||||||
STAT_num_instrs += num_instrs_before;
|
STAT_num_instrs += num_instrs_before;
|
||||||
STAT_num_instrs_removed += num_instrs_before - num_instrs_after;
|
STAT_num_instrs_removed += num_instrs_before - num_instrs_after;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue