From b0cba142a991d2a0c953f54bd97b47314b263e9c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 12 Aug 2022 21:17:19 +0300 Subject: [PATCH] Merge ir_uses_fixed_reg() into ir_get_def_flags() and ir_get_use_flags() --- ir_aarch64.dasc | 66 +++++++++---------------- ir_private.h | 7 ++- ir_ra.c | 9 ++-- ir_x86.dasc | 127 ++++++++++++++++++++++-------------------------- 4 files changed, 89 insertions(+), 120 deletions(-) diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 3289126..9c4c6ce 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -381,38 +381,6 @@ static ir_reg ir_get_arg_reg(ir_ctx *ctx, ir_insn *insn, int op_num) return IR_REG_NONE; } -ir_reg ir_uses_fixed_reg(ir_ctx *ctx, ir_ref ref, int op_num) -{ - ir_ref rule; - - rule = ctx->rules[ref]; - if (rule == IR_RETURN_INT) { - if (op_num == 2) { - return IR_REG_INT_RET1; - } - } else if (rule == IR_RETURN_FP) { - if (op_num == 2) { - return IR_REG_FP_RET1; - } - } else if (rule == IR_SKIP_REG) { - if (ctx->ir_base[ref].op == IR_PARAM && op_num == 0) { - return ir_get_param_reg(ctx, ref); - } - } else if (rule == IR_CALL || (rule == IR_TAILCALL && op_num > 0)) { - ir_insn *insn = &ctx->ir_base[ref]; - if (op_num == 0) { - if (IR_IS_TYPE_INT(insn->type)) { - return IR_REG_INT_RET1; - } else { - return IR_REG_FP_RET1; - } - } else { - return ir_get_arg_reg(ctx, insn, op_num); - } - } - return IR_REG_NONE; -} - static bool ir_call_needs_tmp_int_reg(ir_ctx *ctx, ir_ref ref) { ir_insn *insn = &ctx->ir_base[ref]; @@ -442,34 +410,42 @@ static bool ir_call_needs_tmp_int_reg(ir_ctx *ctx, ir_ref ref) return 0; } -uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref) +uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref, ir_reg *reg) { ir_ref rule = ctx->rules[ref]; ir_insn *insn; + *reg = IR_REG_NONE; switch (rule) { case IR_SKIP_REG: /* PARAM PHI PI */ insn = &ctx->ir_base[ref]; if (insn->op == IR_PARAM) { - if (ir_get_param_reg(ctx, ref) == IR_REG_NONE) { + *reg = ir_get_param_reg(ctx, ref); + if (*reg == IR_REG_NONE) { return IR_USE_MUST_BE_IN_REG; } } return IR_USE_SHOULD_BE_IN_REG; + case IR_CALL: + insn = &ctx->ir_base[ref]; + *reg = (IR_IS_TYPE_INT(insn->type)) ? IR_REG_INT_RET1 : IR_REG_FP_RET1; + break; } return IR_USE_MUST_BE_IN_REG; } -uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num) +uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num, ir_reg *reg) { ir_ref rule = ctx->rules[ref]; IR_ASSERT(op_num > 0); + *reg = IR_REG_NONE; switch (rule) { case IR_CALL: case IR_TAILCALL: if (op_num > 2) { + *reg = ir_get_arg_reg(ctx, &ctx->ir_base[ref], op_num); return IR_USE_SHOULD_BE_IN_REG; } return IR_USE_MUST_BE_IN_REG; @@ -477,11 +453,17 @@ uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num) case IR_ZEXT: case IR_TRUNC: case IR_BITCAST: - case IR_RETURN_INT: - case IR_RETURN_FP: case IR_RSTORE: case IR_SKIP_REG: /* PARAM PHI PI */ return IR_USE_SHOULD_BE_IN_REG; + case IR_RETURN_INT: + IR_ASSERT(op_num == 2); + *reg = IR_REG_INT_RET1; + return IR_USE_SHOULD_BE_IN_REG; + case IR_RETURN_FP: + IR_ASSERT(op_num == 2); + *reg = IR_REG_FP_RET1; + return IR_USE_SHOULD_BE_IN_REG; } return IR_USE_MUST_BE_IN_REG; @@ -4529,6 +4511,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ir_regset available = 0; ir_tmp_reg tmp_regs[4]; uint8_t def_flags; + ir_reg reg; ctx->regs = ir_mem_malloc(sizeof(ir_regs) * ctx->insns_count); memset(ctx->regs, IR_REG_NONE, sizeof(ir_regs) * ctx->insns_count); @@ -4564,7 +4547,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) case IR_SKIP: case IR_SKIP_REG: /* PARAM PHI PI */ /* skip */ - def_flags = ir_get_def_flags(ctx, i); + def_flags = ir_get_def_flags(ctx, i, ®); if (ctx->rules && *rule != IR_CMP_AND_BRANCH_INT && *rule != IR_CMP_AND_BRANCH_FP @@ -4573,8 +4556,6 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) available = IR_REGSET_SCRATCH; } if (ctx->vregs[i]) { - ir_reg reg = ir_uses_fixed_reg(ctx, i, 0); - if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { IR_REGSET_EXCL(available, reg); ctx->regs[i][0] = reg | IR_REG_SPILL_STORE; @@ -4661,14 +4642,15 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ir_reg reg = ctx->regs[i][0] & ~IR_REG_SPILL_STORE; ctx->regs[i][1] = reg | IR_REG_SPILL_LOAD; } else { - ir_reg reg = ir_uses_fixed_reg(ctx, i, j); + ir_reg reg; + uint8_t use_flags = ir_get_use_flags(ctx, i, j, ®); if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { IR_REGSET_EXCL(available, reg); ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD; } else if (j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) { ctx->regs[i][j] = ctx->regs[i][1]; - } else if (ir_get_use_flags(ctx, i, j) & IR_USE_MUST_BE_IN_REG) { + } else if (use_flags & IR_USE_MUST_BE_IN_REG) { reg = ir_get_free_reg(ctx->ir_base[input].type, available); IR_REGSET_EXCL(available, reg); ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD; diff --git a/ir_private.h b/ir_private.h index e413c3d..e7ebbd5 100644 --- a/ir_private.h +++ b/ir_private.h @@ -209,7 +209,7 @@ IR_ALWAYS_INLINE int ir_nlzl(uint64_t num) # define IR_BITSET_BITS 32 # define IR_BITSET_ONE 1U # define ir_bitset_base_t uint32_t -# define IR_bitset_ntz ir_ntz +# define ir_bitset_ntz ir_ntz #else # define IR_BITSET_BITS 64 # define IR_BITSET_ONE 1UL @@ -927,9 +927,8 @@ bool ir_needs_vreg(ir_ctx *ctx, ir_ref ref); /* Registers modified by the given instruction */ ir_regset ir_get_scratch_regset(ir_ctx *ctx, ir_ref ref, ir_live_pos *start, ir_live_pos *end); -ir_reg ir_uses_fixed_reg(ir_ctx *ctx, ir_ref ref, int op_num); -uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref); -uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num); +uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref, ir_reg *reg); +uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num, ir_reg *reg); int ir_get_temporary_regs(ir_ctx *ctx, ir_ref ref, ir_tmp_reg *tmp_regs); #endif /* defined(IR_REGSET_64BIT) */ diff --git a/ir_ra.c b/ir_ra.c index fbf5ce6..0f40694 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -434,8 +434,7 @@ int ir_compute_live_ranges(ir_ctx *ctx) ir_ref hint_ref = 0; if (ctx->rules) { - def_flags = ir_get_def_flags(ctx, i); - reg = ir_uses_fixed_reg(ctx, i, 0); + def_flags = ir_get_def_flags(ctx, i, ®); } else { reg = IR_REG_NONE; } @@ -490,8 +489,7 @@ int ir_compute_live_ranges(ir_ctx *ctx) uint8_t use_flags; if (ctx->rules) { - use_flags = ir_get_use_flags(ctx, i, j); - reg = ir_uses_fixed_reg(ctx, i, j); + use_flags = ir_get_use_flags(ctx, i, j, ®); } else { use_flags = 0; reg = IR_REG_NONE; @@ -929,6 +927,7 @@ int ir_coalesce(ir_ctx *ctx) ir_worklist blocks; bool compact = 0; ir_live_range *unused = NULL; + ir_reg reg; /* Collect a list of blocks which are predecossors to block with phi finctions */ ir_worklist_init(&blocks, ctx->cfg_blocks_count + 1); @@ -999,7 +998,7 @@ int ir_coalesce(ir_ctx *ctx) /* try to swap operands of commutative instructions for better register allocation */ for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) { for (i = bb->start, insn = ctx->ir_base + i; i <= bb->end;) { - if (ir_get_def_flags(ctx, i) & IR_DEF_REUSES_OP1_REG) { + if (ir_get_def_flags(ctx, i, ®) & IR_DEF_REUSES_OP1_REG) { if (insn->op2 > 0 && insn->op1 != insn->op2 && (ir_op_flags[insn->op] & IR_OP_FLAG_COMMUTATIVE)) { ir_try_swap_operands(ctx, i, insn); diff --git a/ir_x86.dasc b/ir_x86.dasc index 2d737fb..a75db51 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -769,56 +769,6 @@ static ir_reg ir_get_arg_reg(ir_ctx *ctx, ir_insn *insn, int op_num) return IR_REG_NONE; } -ir_reg ir_uses_fixed_reg(ir_ctx *ctx, ir_ref ref, int op_num) -{ - ir_ref rule; - - rule = ctx->rules[ref]; - if (rule == IR_SHIFT || rule == IR_SKIP_SHIFT) { - if (op_num == 2) { - return IR_REG_RCX; - } - } else if (rule == IR_MUL_INT || rule == IR_DIV_INT) { - if (op_num == 0 || op_num == 1) { - return IR_REG_RAX; - } - } else if (rule == IR_MOD_INT) { - if (op_num == 0) { - return IR_REG_RDX; - } else if (op_num == 1) { - return IR_REG_RAX; - } - } else if (rule == IR_RETURN_INT) { - if (op_num == 2) { - return IR_REG_INT_RET1; - } -#ifdef IR_REG_FP_RET1 - } else if (rule == IR_RETURN_FP) { - if (op_num == 2) { - return IR_REG_FP_RET1; - } -#endif - } else if (rule == IR_SKIP_REG) { - if (ctx->ir_base[ref].op == IR_PARAM && op_num == 0) { - return ir_get_param_reg(ctx, ref); - } - } else if (rule == IR_CALL || (rule == IR_TAILCALL && op_num > 0)) { - ir_insn *insn = &ctx->ir_base[ref]; - if (op_num == 0) { - if (IR_IS_TYPE_INT(insn->type)) { - return IR_REG_INT_RET1; -#ifdef IR_REG_FP_RET1 - } else { - return IR_REG_FP_RET1; -#endif - } - } else { - return ir_get_arg_reg(ctx, insn, op_num); - } - } - return IR_REG_NONE; -} - static bool ir_call_needs_tmp_int_reg(ir_ctx *ctx, ir_ref ref) { ir_insn *insn = &ctx->ir_base[ref]; @@ -862,18 +812,17 @@ static bool ir_call_needs_tmp_int_reg(ir_ctx *ctx, ir_ref ref) return 0; } -uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref) +uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref, ir_reg *reg) { ir_ref rule = ctx->rules[ref]; ir_insn *insn; + *reg = IR_REG_NONE; switch (rule) { case IR_BINOP_INT: case IR_BINOP_SSE2: case IR_SHIFT: case IR_SHIFT_CONST: - case IR_MUL_INT: - case IR_DIV_INT: case IR_COPY_INT: case IR_COPY_FP: case IR_INC: @@ -890,29 +839,42 @@ uint8_t ir_get_def_flags(ir_ctx *ctx, ir_ref ref) case IR_SKIP_REG: /* PARAM PHI PI */ insn = &ctx->ir_base[ref]; if (insn->op == IR_PARAM) { - if (ir_get_param_reg(ctx, ref) == IR_REG_NONE) { + *reg = ir_get_param_reg(ctx, ref); + if (*reg == IR_REG_NONE) { return IR_USE_MUST_BE_IN_REG; } } return IR_USE_SHOULD_BE_IN_REG; + case IR_MUL_INT: + case IR_DIV_INT: + *reg = IR_REG_RAX; + return IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG; + case IR_MOD_INT : + *reg = IR_REG_RDX; + break; + case IR_CALL: + insn = &ctx->ir_base[ref]; + if (IR_IS_TYPE_INT(insn->type)) { + *reg = IR_REG_INT_RET1; +#ifdef IR_REG_FP_RET1 + } else { + *reg = IR_REG_FP_RET1; +#endif + } + break; } return IR_USE_MUST_BE_IN_REG; } -uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num) +uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num, ir_reg *reg) { ir_ref rule = ctx->rules[ref]; ir_insn *insn; IR_ASSERT(op_num > 0); + *reg = IR_REG_NONE; switch (rule) { - case IR_MUL_INT: - case IR_DIV_INT: - case IR_MOD_INT: - if (op_num == 1) { - return IR_USE_SHOULD_BE_IN_REG; - } case IR_BINOP_INT: case IR_SKIP_BINOP_INT: case IR_BINOP_SSE2: @@ -941,11 +903,11 @@ uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num) case IR_CALL: case IR_TAILCALL: if (op_num > 2) { + insn = &ctx->ir_base[ref]; + *reg = ir_get_arg_reg(ctx, insn, op_num); return IR_USE_SHOULD_BE_IN_REG; } return IR_USE_SHOULD_BE_IN_REG; - case IR_RETURN_INT: - case IR_RETURN_FP: case IR_IJMP: case IR_RSTORE: case IR_SKIP_REG: /* PARAM PHI PI */ @@ -981,8 +943,35 @@ uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num) break; } break; - } + case IR_SHIFT: + case IR_SKIP_SHIFT: + if (op_num == 2) { + *reg = IR_REG_RCX; + } + break; + case IR_MUL_INT: + case IR_DIV_INT: + if (op_num == 1) { + *reg = IR_REG_RAX; + } + return IR_USE_SHOULD_BE_IN_REG; + case IR_MOD_INT: + if (op_num == 1) { + *reg = IR_REG_RAX; + } + return IR_USE_SHOULD_BE_IN_REG; + case IR_RETURN_INT: + IR_ASSERT(op_num == 2); + *reg = IR_REG_INT_RET1; + return IR_USE_SHOULD_BE_IN_REG; + case IR_RETURN_FP: +#ifdef IR_REG_FP_RET1 + IR_ASSERT(op_num == 2); + *reg = IR_REG_FP_RET1; +#endif + return IR_USE_SHOULD_BE_IN_REG; + } return IR_USE_MUST_BE_IN_REG; } @@ -6502,6 +6491,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ir_regset available = 0; ir_tmp_reg tmp_regs[4]; uint8_t def_flags; + ir_reg reg; #ifndef IR_REG_FP_RET1 ir_type ret_type = ir_get_return_type(ctx); @@ -6551,7 +6541,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) case IR_SKIP_MEM: case IR_SKIP_REG: /* PARAM PHI PI */ /* skip */ - def_flags = ir_get_def_flags(ctx, i); + def_flags = ir_get_def_flags(ctx, i, ®); if (ctx->rules && *rule != IR_CMP_AND_BRANCH_INT && *rule != IR_CMP_AND_BRANCH_FP @@ -6560,8 +6550,6 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) available = IR_REGSET_SCRATCH; } if (ctx->vregs[i]) { - ir_reg reg = ir_uses_fixed_reg(ctx, i, 0); - if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { IR_REGSET_EXCL(available, reg); ctx->regs[i][0] = reg | IR_REG_SPILL_STORE; @@ -6648,14 +6636,15 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx) ir_reg reg = ctx->regs[i][0] & ~IR_REG_SPILL_STORE; ctx->regs[i][1] = reg | IR_REG_SPILL_LOAD; } else { - ir_reg reg = ir_uses_fixed_reg(ctx, i, j); + ir_reg reg; + uint8_t use_flags = ir_get_use_flags(ctx, i, j, ®); if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { IR_REGSET_EXCL(available, reg); ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD; } else if (j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) { ctx->regs[i][j] = ctx->regs[i][1]; - } else if (ir_get_use_flags(ctx, i, j) & IR_USE_MUST_BE_IN_REG) { + } else if (use_flags & IR_USE_MUST_BE_IN_REG) { reg = ir_get_free_reg(ctx->ir_base[input].type, available); IR_REGSET_EXCL(available, reg); ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD;