diff options
-rw-r--r-- | src/freedreno/ir3/ir3_ra.c | 3 | ||||
-rw-r--r-- | src/util/register_allocate.c | 25 | ||||
-rw-r--r-- | src/util/register_allocate.h | 5 |
3 files changed, 31 insertions, 2 deletions
diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index 9f0d71f9f4e..789c08f42ed 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -297,8 +297,7 @@ ir3_ra_alloc_reg_set(struct ir3_compiler *compiler) unsigned hreg0 = set->gpr_to_ra_reg[i + HALF_OFFSET][(j * 2) + 0]; unsigned hreg1 = set->gpr_to_ra_reg[i + HALF_OFFSET][(j * 2) + 1]; - ra_add_transitive_reg_conflict(set->regs, freg, hreg0); - ra_add_transitive_reg_conflict(set->regs, freg, hreg1); + ra_add_transitive_reg_pair_conflict(set->regs, freg, hreg0, hreg1); } } diff --git a/src/util/register_allocate.c b/src/util/register_allocate.c index b23bb377292..35273630459 100644 --- a/src/util/register_allocate.c +++ b/src/util/register_allocate.c @@ -305,6 +305,31 @@ ra_add_transitive_reg_conflict(struct ra_regs *regs, } /** + * Set up conflicts between base_reg and it's two half registers reg0 and + * reg1, but take care to not add conflicts between reg0 and reg1. + * + * This is useful for architectures where full size registers are aliased by + * two half size registers (eg 32 bit float and 16 bit float registers). + */ +void +ra_add_transitive_reg_pair_conflict(struct ra_regs *regs, + unsigned int base_reg, unsigned int reg0, unsigned int reg1) +{ + unsigned int i; + + ra_add_reg_conflict(regs, reg0, base_reg); + ra_add_reg_conflict(regs, reg1, base_reg); + + for (i = 0; i < regs->regs[base_reg].num_conflicts; i++) { + unsigned int conflict = regs->regs[base_reg].conflict_list[i]; + if (conflict != reg1) + ra_add_reg_conflict(regs, reg0, regs->regs[base_reg].conflict_list[i]); + if (conflict != reg0) + ra_add_reg_conflict(regs, reg1, regs->regs[base_reg].conflict_list[i]); + } +} + +/** * Makes every conflict on the given register transitive. In other words, * every register that conflicts with r will now conflict with every other * register conflicting with r. diff --git a/src/util/register_allocate.h b/src/util/register_allocate.h index 2cb57a1f0be..fcd4d9394e0 100644 --- a/src/util/register_allocate.h +++ b/src/util/register_allocate.h @@ -55,6 +55,11 @@ void ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2); void ra_add_transitive_reg_conflict(struct ra_regs *regs, unsigned int base_reg, unsigned int reg); + +void +ra_add_transitive_reg_pair_conflict(struct ra_regs *regs, + unsigned int base_reg, unsigned int reg0, unsigned int reg1); + void ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int reg); void ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int reg); void ra_set_num_conflicts(struct ra_regs *regs, unsigned int class_a, |