diff --git a/ir.h b/ir.h index a469d93..cff113d 100644 --- a/ir.h +++ b/ir.h @@ -505,6 +505,7 @@ void ir_strtab_free(ir_strtab *strtab); # define IR_DEBUG_GCM (1<<28) # define IR_DEBUG_SCHEDULE (1<<29) # define IR_DEBUG_RA (1<<30) +# define IR_DEBUG_CODEGEN (1<<31) #endif typedef struct _ir_ctx ir_ctx; diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index f5f30c2..3c1645a 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -217,38 +217,54 @@ const char *ir_reg_name(int8_t reg, ir_type type) } } +#define IR_RULES(_) \ + _(CMP_INT) \ + _(CMP_FP) \ + _(MUL_PWR2) \ + _(DIV_PWR2) \ + _(MOD_PWR2) \ + _(OP_INT) \ + _(OP_FP) \ + _(BINOP_INT) \ + _(BINOP_FP) \ + _(SHIFT) \ + _(SHIFT_CONST) \ + _(COPY_INT) \ + _(COPY_FP) \ + _(CMP_AND_BRANCH_INT) \ + _(CMP_AND_BRANCH_FP) \ + _(GUARD_CMP_INT) \ + _(GUARD_CMP_FP) \ + _(GUARD_OVERFLOW) \ + _(OVERFLOW_AND_BRANCH) \ + _(MIN_MAX_INT) \ + _(REG_BINOP_INT) \ + _(LOAD_INT) \ + _(LOAD_FP) \ + _(STORE_INT) \ + _(STORE_FP) \ + _(IF_INT) \ + _(RETURN_VOID) \ + _(RETURN_INT) \ + _(RETURN_FP) \ + +#define IR_RULE_ENUM(name) IR_ ## name, + enum _ir_rule { - IR_CMP_INT = IR_LAST_OP, - IR_CMP_FP, - IR_MUL_PWR2, - IR_DIV_PWR2, - IR_MOD_PWR2, - IR_OP_INT, - IR_OP_FP, - IR_BINOP_INT, - IR_BINOP_FP, - IR_SHIFT, - IR_SHIFT_CONST, - IR_COPY_INT, - IR_COPY_FP, - IR_CMP_AND_BRANCH_INT, - IR_CMP_AND_BRANCH_FP, - IR_GUARD_CMP_INT, - IR_GUARD_CMP_FP, - IR_GUARD_OVERFLOW, - IR_OVERFLOW_AND_BRANCH, - IR_MIN_MAX_INT, - IR_REG_BINOP_INT, - IR_LOAD_INT, - IR_LOAD_FP, - IR_STORE_INT, - IR_STORE_FP, - IR_IF_INT, - IR_RETURN_VOID, - IR_RETURN_INT, - IR_RETURN_FP, + IR_FIRST_RULE = IR_LAST_OP, + IR_RULES(IR_RULE_ENUM) + IR_LAST_RULE }; +#ifdef IR_DEBUG +#define IR_RULE_NAME(name) #name, +const char *ir_rule_name[IR_LAST_OP] = { + NULL, + IR_RULES(IR_RULE_NAME) + NULL +}; +#endif + /* register allocation */ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints) { diff --git a/ir_main.c b/ir_main.c index 2592ca0..49e8b02 100644 --- a/ir_main.c +++ b/ir_main.c @@ -332,6 +332,8 @@ int main(int argc, char **argv) flags |= IR_DEBUG_SCHEDULE; } else if (strcmp(argv[i], "--debug-ra") == 0) { flags |= IR_DEBUG_RA; + } else if (strcmp(argv[i], "--debug-codegen") == 0) { + flags |= IR_DEBUG_CODEGEN; #endif } else if (strcmp(argv[i], "--debug-regset") == 0) { if (i + 1 == argc || argv[i + 1][0] == '-') { diff --git a/ir_private.h b/ir_private.h index e4e7321..bb666df 100644 --- a/ir_private.h +++ b/ir_private.h @@ -1123,6 +1123,8 @@ IR_ALWAYS_INLINE ir_reg ir_regset_pop_first(ir_regset *set) } \ } while (0) +#endif /* defined(IR_REGSET_64BIT) */ + /*** IR Register Allocation ***/ /* Flags for ctx->regs[][] (low bits are used for register number itself) */ typedef struct _ir_reg_alloc_data { @@ -1162,6 +1164,10 @@ IR_ALWAYS_INLINE int8_t ir_get_alocated_reg(const ir_ctx *ctx, ir_ref ref, int o #define IR_RULE_MASK 0xff +#ifdef IR_DEBUG +extern const char *ir_rule_name[]; +#endif + typedef struct _ir_target_constraints ir_target_constraints; #define IR_TMP_REG(_num, _type, _start, _end) \ @@ -1171,8 +1177,6 @@ typedef struct _ir_target_constraints ir_target_constraints; int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints); -#endif /* defined(IR_REGSET_64BIT) */ - //#define IR_BITSET_LIVENESS #endif /* IR_PRIVATE_H */ diff --git a/ir_save.c b/ir_save.c index 64e0019..a65d6a8 100644 --- a/ir_save.c +++ b/ir_save.c @@ -14,6 +14,9 @@ void ir_save(const ir_ctx *ctx, FILE *f) ir_insn *insn; uint32_t flags; bool first; +#ifdef IR_DEBUG + bool verbose = (ctx->flags & IR_DEBUG_CODEGEN); +#endif fprintf(f, "{\n"); for (i = IR_UNUSED + 1, insn = ctx->ir_base - i; i < ctx->consts_count; i++, insn--) { @@ -40,6 +43,11 @@ void ir_save(const ir_ctx *ctx, FILE *f) for (i = IR_UNUSED + 1, insn = ctx->ir_base + i; i < ctx->insns_count;) { flags = ir_op_flags[insn->op]; if (flags & IR_OP_FLAG_CONTROL) { +#ifdef IR_DEBUG + if (verbose && ctx->cfg_map && (flags & IR_OP_FLAG_BB_START)) { + fprintf(f, "#BB%d:\n", ctx->cfg_map[i]); + } +#endif if (!(flags & IR_OP_FLAG_MEM) || insn->type == IR_VOID) { fprintf(f, "\tl_%d = ", i); } else { @@ -48,7 +56,20 @@ void ir_save(const ir_ctx *ctx, FILE *f) } else { fprintf(f, "\t"); if (flags & IR_OP_FLAG_DATA) { - fprintf(f, "%s d_%d = ", ir_type_cname[insn->type], i); + fprintf(f, "%s d_%d", ir_type_cname[insn->type], i); +#ifdef IR_DEBUG + if (verbose && ctx->vregs && ctx->vregs[i]) { + fprintf(f, " {R%d}", ctx->vregs[i]); + } + if (verbose && ctx->regs) { + int8_t reg = ctx->regs[i][0]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), + (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); + } + } +#endif + fprintf(f, " = "); } } fprintf(f, "%s", ir_op_name[insn->op]); @@ -75,6 +96,18 @@ void ir_save(const ir_ctx *ctx, FILE *f) } else { fprintf(f, "%sd_%d", first ? "(" : ", ", ref); } +#ifdef IR_DEBUG + if (verbose && ctx->vregs && ref > 0 && ctx->vregs[ref]) { + fprintf(f, " {R%d}", ctx->vregs[ref]); + } + if (verbose && ctx->regs) { + int8_t reg = ctx->regs[i][j]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), + (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); + } + } +#endif first = 0; break; case IR_OPND_CONTROL: @@ -117,7 +150,82 @@ void ir_save(const ir_ctx *ctx, FILE *f) fprintf(f, " # BIND(0x%x);", -var); } } +#ifdef IR_DEBUG + if (verbose && ctx->rules) { + uint32_t rule = ctx->rules[i]; + uint32_t id = rule & ~(IR_FUSED|IR_SKIPPED|IR_SIMPLE); + + if (id < IR_LAST_OP) { + fprintf(f, " # RULE(%s", ir_op_name[id]); + } else { + IR_ASSERT(id > IR_LAST_OP /*&& id < IR_LAST_RULE*/); + fprintf(f, " # RULE(%s", ir_rule_name[id - IR_LAST_OP]); + } + if (rule & IR_FUSED) { + fprintf(f, ":FUSED"); + } + if (rule & IR_SKIPPED) { + fprintf(f, ":SKIPPED"); + } + if (rule & IR_SIMPLE) { + fprintf(f, ":SIMPLE"); + } + fprintf(f, ")"); + } +#endif fprintf(f, "\n"); +#ifdef IR_DEBUG + if (verbose && ctx->cfg_map && (flags & IR_OP_FLAG_BB_END)) { + uint32_t b = ctx->cfg_map[i]; + ir_block *bb = &ctx->cfg_blocks[b]; + + if (bb->flags & IR_BB_DESSA_MOVES) { + uint32_t succ; + ir_block *succ_bb; + ir_use_list *use_list; + ir_ref k, i, *p, use_ref, input; + ir_insn *use_insn; + + IR_ASSERT(bb->successors_count == 1); + succ = ctx->cfg_edges[bb->successors]; + succ_bb = &ctx->cfg_blocks[succ]; + IR_ASSERT(succ_bb->predecessors_count > 1); + use_list = &ctx->use_lists[succ_bb->start]; + k = ir_phi_input_number(ctx, succ_bb, b); + + for (i = 0, p = &ctx->use_edges[use_list->refs]; i < use_list->count; i++, p++) { + use_ref = *p; + use_insn = &ctx->ir_base[use_ref]; + if (use_insn->op == IR_PHI) { + input = ir_insn_op(use_insn, k); + if (IR_IS_CONST_REF(input)) { + fprintf(f, "\t# DESSA MOV c_%d", -input); + } else if (ctx->vregs[input] != ctx->vregs[use_ref]) { + fprintf(f, "\t# DESSA MOV d_%d {R%d}", input, ctx->vregs[input]); + } else { + continue; + } + if (ctx->regs) { + int8_t reg = ctx->regs[use_ref][k]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), + (reg & (IR_REG_SPILL_LOAD|IR_REG_SPILL_SPECIAL)) ? ":load" : ""); + } + } + fprintf(f, " -> d_%d {R%d}", use_ref, ctx->vregs[use_ref]); + if (ctx->regs) { + int8_t reg = ctx->regs[use_ref][0]; + if (reg != IR_REG_NONE) { + fprintf(f, " {%%%s%s}", ir_reg_name(IR_REG_NUM(reg), ctx->ir_base[ref].type), + (reg & (IR_REG_SPILL_STORE|IR_REG_SPILL_SPECIAL)) ? ":store" : ""); + } + } + fprintf(f, "\n"); + } + } + } + } +#endif n = ir_insn_inputs_to_len(n); i += n; insn += n; diff --git a/ir_test.c b/ir_test.c index 0b3cdea..f1f3ee5 100644 --- a/ir_test.c +++ b/ir_test.c @@ -127,6 +127,8 @@ int main(int argc, char **argv) flags |= IR_DEBUG_SCHEDULE; } else if (strcmp(argv[i], "--debug-ra") == 0) { flags |= IR_DEBUG_RA; + } else if (strcmp(argv[i], "--debug-codegen") == 0) { + flags |= IR_DEBUG_CODEGEN; #endif } else if (strcmp(argv[i], "--debug-regset") == 0) { if (i + 1 == argc || argv[i + 1][0] == '-') { diff --git a/ir_x86.dasc b/ir_x86.dasc index 5a4d49b..24ee5f7 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -441,78 +441,94 @@ const char *ir_reg_name(int8_t reg, ir_type type) return NULL; } +#define IR_RULES(_) \ + _(CMP_INT) \ + _(CMP_FP) \ + _(MUL_INT) \ + _(DIV_INT) \ + _(MOD_INT) \ + _(TEST_INT) \ + _(SETCC_INT) \ + _(TESTCC_INT) \ + _(LEA_OB) \ + _(LEA_SI) \ + _(LEA_SIB) \ + _(LEA_IB) \ + _(LEA_SI_O) \ + _(LEA_SIB_O) \ + _(LEA_IB_O) \ + _(LEA_I_OB) \ + _(LEA_OB_I) \ + _(LEA_OB_SI) \ + _(LEA_SI_OB) \ + _(LEA_B_SI) \ + _(LEA_SI_B) \ + _(INC) \ + _(DEC) \ + _(MUL_PWR2) \ + _(DIV_PWR2) \ + _(MOD_PWR2) \ + _(BOOL_NOT_INT) \ + _(ABS_INT) \ + _(OP_INT) \ + _(OP_FP) \ + _(IMUL3) \ + _(BINOP_INT) \ + _(BINOP_SSE2) \ + _(BINOP_AVX) \ + _(SHIFT) \ + _(SHIFT_CONST) \ + _(COPY_INT) \ + _(COPY_FP) \ + _(CMP_AND_BRANCH_INT) \ + _(CMP_AND_BRANCH_FP) \ + _(TEST_AND_BRANCH_INT) \ + _(JCC_INT) \ + _(GUARD_CMP_INT) \ + _(GUARD_CMP_FP) \ + _(GUARD_TEST_INT) \ + _(GUARD_JCC_INT) \ + _(GUARD_OVERFLOW) \ + _(OVERFLOW_AND_BRANCH) \ + _(MIN_MAX_INT) \ + _(MEM_OP_INT) \ + _(MEM_INC) \ + _(MEM_DEC) \ + _(MEM_MUL_PWR2) \ + _(MEM_DIV_PWR2) \ + _(MEM_MOD_PWR2) \ + _(MEM_BINOP_INT) \ + _(MEM_SHIFT) \ + _(MEM_SHIFT_CONST) \ + _(REG_BINOP_INT) \ + _(VSTORE_INT) \ + _(VSTORE_FP) \ + _(LOAD_INT) \ + _(LOAD_FP) \ + _(STORE_INT) \ + _(STORE_FP) \ + _(IF_INT) \ + _(RETURN_VOID) \ + _(RETURN_INT) \ + _(RETURN_FP) \ + +#define IR_RULE_ENUM(name) IR_ ## name, + enum _ir_rule { - IR_CMP_INT = IR_LAST_OP, - IR_CMP_FP, - IR_MUL_INT, - IR_DIV_INT, - IR_MOD_INT, - IR_TEST_INT, - IR_SETCC_INT, - IR_TESTCC_INT, - IR_LEA_OB, - IR_LEA_SI, - IR_LEA_SIB, - IR_LEA_IB, - IR_LEA_SI_O, - IR_LEA_SIB_O, - IR_LEA_IB_O, - IR_LEA_I_OB, - IR_LEA_OB_I, - IR_LEA_OB_SI, - IR_LEA_SI_OB, - IR_LEA_B_SI, - IR_LEA_SI_B, - IR_INC, - IR_DEC, - IR_MUL_PWR2, - IR_DIV_PWR2, - IR_MOD_PWR2, - IR_BOOL_NOT_INT, - IR_ABS_INT, - IR_OP_INT, - IR_OP_FP, - IR_IMUL3, - IR_BINOP_INT, - IR_BINOP_SSE2, - IR_BINOP_AVX, - IR_SHIFT, - IR_SHIFT_CONST, - IR_COPY_INT, - IR_COPY_FP, - IR_CMP_AND_BRANCH_INT, - IR_CMP_AND_BRANCH_FP, - IR_TEST_AND_BRANCH_INT, - IR_JCC_INT, - IR_GUARD_CMP_INT, - IR_GUARD_CMP_FP, - IR_GUARD_TEST_INT, - IR_GUARD_JCC_INT, - IR_GUARD_OVERFLOW, - IR_OVERFLOW_AND_BRANCH, - IR_MIN_MAX_INT, - IR_MEM_OP_INT, - IR_MEM_INC, - IR_MEM_DEC, - IR_MEM_MUL_PWR2, - IR_MEM_DIV_PWR2, - IR_MEM_MOD_PWR2, - IR_MEM_BINOP_INT, - IR_MEM_SHIFT, - IR_MEM_SHIFT_CONST, - IR_REG_BINOP_INT, - IR_VSTORE_INT, - IR_VSTORE_FP, - IR_LOAD_INT, - IR_LOAD_FP, - IR_STORE_INT, - IR_STORE_FP, - IR_IF_INT, - IR_RETURN_VOID, - IR_RETURN_INT, - IR_RETURN_FP, + IR_FIRST_RULE = IR_LAST_OP, + IR_RULES(IR_RULE_ENUM) + IR_LAST_RULE }; +#ifdef IR_DEBUG +#define IR_RULE_NAME(name) #name, +const char *ir_rule_name[IR_LAST_OP] = { + NULL, + IR_RULES(IR_RULE_NAME) + NULL +}; +#endif + /* register allocation */ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constraints *constraints) {