Add "must be in reg" constraint

This commit is contained in:
Dmitry Stogov 2022-04-28 14:48:43 +03:00
parent ea46798aeb
commit 3e6f84eef4
5 changed files with 34 additions and 1 deletions

2
TODO
View File

@ -37,7 +37,7 @@
- constraints
- kill
- restricted regset
- must be in register
+ must be in register
- temporary registers
? spills
- spill slot allocation (packed/aligned according to SpillRange)

4
ir.h
View File

@ -517,9 +517,13 @@ typedef struct _ir_live_interval ir_live_interval;
#define IR_LIVE_INTERVAL_COALESCED (1<<0)
#define IR_USE_MUST_BE_IN_REG (1<<0)
#define IR_USE_SHOULD_BE_IN_REG (1<<1)
struct _ir_use_pos {
uint16_t op_num; /* 0 - means result */
int8_t hint;
uint8_t flags;
ir_ref hint_ref;
ir_live_pos pos;
ir_use_pos *next;

10
ir_ra.c
View File

@ -219,6 +219,7 @@ static void ir_add_use(ir_ctx *ctx, int v, int op_num, ir_live_pos pos, ir_reg h
use_pos->hint = hint;
use_pos->hint_ref = hint_ref;
use_pos->pos = pos;
use_pos->flags = ctx->rules ? ir_get_use_flags(ctx, IR_LIVE_POS_TO_REF(pos), op_num) : 0;
ir_add_use_pos(ctx, v, use_pos);
}
@ -1284,6 +1285,9 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, int current, uint32_t len, ir
// TODO: skip usages that don't require register
use_pos = use_pos->next;
}
while (use_pos && !(use_pos->flags & IR_USE_MUST_BE_IN_REG)) {
use_pos = use_pos->next;
}
if (!use_pos) {
/* spill */
return IR_REG_NONE;
@ -1328,6 +1332,9 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, int current, uint32_t len, ir
while (use_pos && use_pos->pos <= ival->range.start) { // TODO: less or less-or-equal
use_pos = use_pos->next;
}
while (use_pos && !(use_pos->flags & (IR_USE_MUST_BE_IN_REG|IR_USE_SHOULD_BE_IN_REG))) {
use_pos = use_pos->next;
}
if (use_pos && use_pos->pos < nextUsePos[reg]) {
nextUsePos[reg] = use_pos->pos;
}
@ -1357,6 +1364,9 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, int current, uint32_t len, ir
while (use_pos && use_pos->pos < ival->range.start) {
use_pos = use_pos->next;
}
while (use_pos && !(use_pos->flags & (IR_USE_MUST_BE_IN_REG|IR_USE_SHOULD_BE_IN_REG))) {
use_pos = use_pos->next;
}
if (use_pos && use_pos->pos < nextUsePos[reg]) {
nextUsePos[reg] = use_pos->pos;
}

View File

@ -946,6 +946,24 @@ bool ir_result_reuses_op1_reg(ir_ctx *ctx, ir_ref ref)
return 0;
}
uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num)
{
ir_ref rule;
rule = ctx->rules[ref];
switch (rule) {
case IR_BINOP_INT:
case IR_BINOP_SSE2:
case IR_BINOP_AVX:
case IR_MUL_INT:
case IR_DIV_INT:
case IR_MOD_INT:
return (op_num == 2) ? IR_USE_SHOULD_BE_IN_REG : IR_USE_MUST_BE_IN_REG;
}
return IR_USE_MUST_BE_IN_REG;
}
static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref, ir_block *bb)
{
ir_insn *op2_insn;

View File

@ -281,5 +281,6 @@ bool ir_needs_vreg(ir_ctx *ctx, ir_ref ref);
ir_regset ir_get_scratch_regset(ir_ctx *ctx, ir_ref ref);
ir_reg ir_uses_fixed_reg(ir_ctx *ctx, ir_ref ref, int op_num);
bool ir_result_reuses_op1_reg(ir_ctx *ctx, ir_ref ref);
uint8_t ir_get_use_flags(ir_ctx *ctx, ir_ref ref, int op_num);
#endif /* IR_X86_H */