summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/freedreno/ir3/ir3_ra.c3
-rw-r--r--src/util/register_allocate.c25
-rw-r--r--src/util/register_allocate.h5
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,