diff --git a/src/jit/backend/x64/x64_backend.cc b/src/jit/backend/x64/x64_backend.cc index 1223c656..9fe1e574 100644 --- a/src/jit/backend/x64/x64_backend.cc +++ b/src/jit/backend/x64/x64_backend.cc @@ -1609,6 +1609,8 @@ EMITTER(CALL_FALLBACK) { e.call(fallback); } +EMITTER(DEBUG_INFO) {} + void x64_backend_destroy(struct jit_backend *jit_backend) { struct x64_backend *backend = (struct x64_backend *)jit_backend; diff --git a/src/jit/frontend/sh4/sh4_translate.c b/src/jit/frontend/sh4/sh4_translate.c index f07bccf0..a1c19e16 100644 --- a/src/jit/frontend/sh4/sh4_translate.c +++ b/src/jit/frontend/sh4/sh4_translate.c @@ -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, const struct sh4_instr *instr, 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); } diff --git a/src/jit/ir/ir.c b/src/jit/ir/ir.c index cce50e2a..016e8945 100644 --- a/src/jit/ir/ir.c +++ b/src/jit/ir/ir.c @@ -21,7 +21,7 @@ static struct ir_instr *ir_alloc_instr(struct ir *ir, enum ir_op op) { instr->op = op; - // initialize use links + /* initialize use links */ for (int i = 0; i < MAX_INSTR_ARGS; i++) { struct ir_use *use = &instr->used[i]; 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) { struct ir_instr *instr = ir_alloc_instr(ir, op); - // allocate result if needed + /* allocate result if needed */ if (result_type != VALUE_V) { struct ir_value *result = ir_calloc(ir, sizeof(struct ir_value)); 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) { - // 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++) { 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) { - // align local to natural size + /* align local to natural size */ int type_size = ir_type_size(type); 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) { + /* replace all uses of v with other */ CHECK_NE(v, other); 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_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); +} diff --git a/src/jit/ir/ir.h b/src/jit/ir/ir.h index 9bf9aab2..3855c270 100644 --- a/src/jit/ir/ir.h +++ b/src/jit/ir/ir.h @@ -41,16 +41,16 @@ enum ir_cmp { struct ir_value; struct ir_instr; -// 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 -// value of the arguments that reference it +/* 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 + value of the arguments that reference it */ struct ir_use { - // the instruction that's using the value + /* the instruction that's using the value */ struct ir_instr *instr; - // 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 - // removed (e.g. due to constant propagation) + /* 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 + removed (e.g. due to constant propagation) */ struct ir_value **parg; struct list_node it; @@ -69,16 +69,16 @@ struct ir_value { char *str; }; - // instruction that defines this value (non-constant values) + /* instruction that defines this value (non-constant values) */ struct ir_instr *def; - // instructions that use this value as an argument + /* instructions that use this value as an argument */ struct list uses; - // host register allocated for this value + /* host register allocated for this value */ int reg; - // generic meta data used by optimization passes + /* generic meta data used by optimization passes */ intptr_t tag; }; @@ -87,24 +87,24 @@ struct ir_value { struct ir_instr { enum ir_op op; - // 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 - // instr->arg[0].value) + /* 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 + instr->arg[0].value) */ struct ir_value *arg[MAX_INSTR_ARGS]; struct ir_use used[MAX_INSTR_ARGS]; - // result of the instruction. note, instruction results don't consider - // themselves users of the value (eases register allocation logic) + /* result of the instruction. note, instruction results don't consider + themselves users of the value (eases register allocation logic) */ struct ir_value *result; - // generic meta data used by optimization passes + /* generic meta data used by optimization passes */ intptr_t tag; struct list_node it; }; -// locals are allocated for values that need to be spilled to the stack -// during register allocation +/* locals are allocated for values that need to be spilled to the stack + during register allocation */ struct ir_local { enum ir_type type; 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); -// direct access to host memory +/* direct access to host memory */ struct ir_value *ir_load(struct ir *ir, struct ir_value *addr, enum ir_type type); 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, enum ir_type type); 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); 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, enum ir_type type); 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); 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, enum ir_type dest_type); 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, enum ir_type dest_type); -// conditionals +/* conditionals */ struct ir_value *ir_select(struct ir *ir, struct ir_value *cond, struct ir_value *t, struct ir_value *f); 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 *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_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); @@ -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_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_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); @@ -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_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_vadd(struct ir *ir, struct ir_value *a, struct ir_value *b, 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, 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_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); @@ -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_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_branch(struct ir *ir, struct ir_value *dst); void ir_branch_false(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_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, @@ -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, uint32_t raw_instr); +/* debug */ +void ir_debug_info(struct ir *ir, uint32_t addr, struct ir_value *data); + #endif diff --git a/src/jit/ir/ir_ops.inc b/src/jit/ir/ir_ops.inc index 04b83013..4e1cf524 100644 --- a/src/jit/ir/ir_ops.inc +++ b/src/jit/ir/ir_ops.inc @@ -51,3 +51,4 @@ IR_OP(BRANCH_FALSE) IR_OP(BRANCH_TRUE) IR_OP(CALL) IR_OP(CALL_FALLBACK) +IR_OP(DEBUG_INFO) diff --git a/tools/recc/recc.c b/tools/recc/recc.c index e5541230..465e3cd0 100644 --- a/tools/recc/recc.c +++ b/tools/recc/recc.c @@ -18,6 +18,7 @@ DEFINE_OPTION_STRING(pass, "lse,cve,esimp,dce,ra", DEFINE_OPTION_INT(stats, 1, "Print pass stats"); 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(num_instrs, "Total instructions"); DEFINE_STAT(num_instrs_removed, "Total instructions removed"); @@ -51,12 +52,20 @@ static void process_file(struct jit *jit, const char *filename, fclose(input); 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 */ char passes[MAX_OPTION_LENGTH]; strncpy(passes, OPTION_pass, sizeof(passes)); + int num_instrs_before = get_num_instrs(&ir); + char *name = strtok(passes, ","); while (name) { if (!strcmp(name, "lse")) { @@ -85,12 +94,13 @@ static void process_file(struct jit *jit, const char *filename, 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); } - int num_instrs_after = get_num_instrs(&ir); STAT_num_instrs += num_instrs_before; STAT_num_instrs_removed += num_instrs_before - num_instrs_after;