summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r--src/gallium/drivers/freedreno/ir3/instr-a3xx.h3
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.h35
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_compiler.c46
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_cp.c3
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_dump.c16
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_ra.c19
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_sched.c11
7 files changed, 53 insertions, 80 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
index b7e19c8ae39..c685fb15666 100644
--- a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
+++ b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
@@ -204,9 +204,6 @@ typedef enum {
/* branches/flow control */
OPC_META_FLOW = 4,
OPC_META_PHI = 5,
- /* relative addressing */
- OPC_META_DEREF = 6,
-
} opc_t;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h
index 3d3ad07c330..30932854884 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.h
+++ b/src/gallium/drivers/freedreno/ir3/ir3.h
@@ -79,18 +79,19 @@ struct ir3_register {
* the component is in the low two bits of the reg #, so
* rN.x becomes: (N << 2) | x
*/
- int num;
+ int num;
/* immediate: */
- int iim_val;
- float fim_val;
+ int iim_val;
+ float fim_val;
/* relative: */
- int offset;
- /* for IR3_REG_SSA, src registers contain ptr back to
- * assigning instruction.
- */
- struct ir3_instruction *instr;
+ int offset;
};
+ /* for IR3_REG_SSA, src registers contain ptr back to
+ * assigning instruction.
+ */
+ struct ir3_instruction *instr;
+
union {
/* used for cat5 instructions, but also for internal/IR level
* tracking of what registers are read/written by an instruction.
@@ -209,9 +210,6 @@ struct ir3_instruction {
struct {
struct ir3_block *block;
} inout;
- struct {
- int off; /* offset relative to addr reg */
- } deref;
/* XXX keep this as big as all other union members! */
uint32_t info[3];
@@ -260,6 +258,12 @@ struct ir3_instruction {
struct ir3_instruction *left, *right;
uint16_t left_cnt, right_cnt;
} cp;
+
+ /* an instruction can reference at most one address register amongst
+ * it's src/dst registers. Beyond that, you need to insert mov's.
+ */
+ struct ir3_instruction *address;
+
struct ir3_instruction *next;
#ifdef DEBUG
uint32_t serialno;
@@ -445,11 +449,6 @@ static inline bool is_meta(struct ir3_instruction *instr)
return (instr->category == -1);
}
-static inline bool is_addr(struct ir3_instruction *instr)
-{
- return is_meta(instr) && (instr->opc == OPC_META_DEREF);
-}
-
static inline bool writes_addr(struct ir3_instruction *instr)
{
if (instr->regs_count > 0) {
@@ -499,11 +498,15 @@ static inline bool reg_gpr(struct ir3_register *r)
static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
{
+ if (instr->address)
+ return instr->regs_count + 1;
return instr->regs_count;
}
static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr, unsigned n)
{
+ if (n == (instr->regs_count + 0))
+ return instr->address;
return ssa(instr->regs[n]);
}
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
index 8551eeb11f7..4b73390fd33 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
@@ -624,16 +624,18 @@ ssa_src(struct ir3_compile_context *ctx, struct ir3_register *reg,
* we must generate a fanin instruction to collect all possible
* array elements that the instruction could address together:
*/
- unsigned i, j, aid = src_array_id(ctx, src);
+ unsigned aid = src_array_id(ctx, src);
+ unsigned first = ctx->array[aid].first;
+ unsigned last = ctx->array[aid].last;
+ unsigned off = src->Index - first; /* vec4 offset */
+ unsigned i, j;
+
+ reg->size = 4 * (1 + last - first);
+ reg->offset = regid(off, chan);
if (ctx->array[aid].fanin) {
instr = ctx->array[aid].fanin;
} else {
- unsigned first, last;
-
- first = ctx->array[aid].first;
- last = ctx->array[aid].last;
-
instr = ir3_instr_create2(ctx->block, -1, OPC_META_FI,
1 + (4 * (last + 1 - first)));
ir3_reg_create(instr, 0, 0);
@@ -756,7 +758,6 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
{
unsigned flags = 0, num = 0;
struct ir3_register *reg;
- struct ir3_instruction *orig = NULL;
switch (src->File) {
case TGSI_FILE_IMMEDIATE:
@@ -815,28 +816,15 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
/* shouldn't happen, and we can't cope with it below: */
compile_assert(ctx, wrmask == 0x1);
- /* wrap in a meta-deref to track both the src and address: */
- orig = instr;
-
- instr = ir3_instr_create(ctx->block, -1, OPC_META_DEREF);
- ir3_reg_create(instr, 0, 0);
- ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = ctx->block->address;
+ compile_assert(ctx, ctx->block->address);
+ if (instr->address)
+ compile_assert(ctx, ctx->block->address == instr->address);
- if (src->File != TGSI_FILE_CONSTANT) {
- unsigned aid = src_array_id(ctx, src);
- unsigned off = src->Index - ctx->array[aid].first; /* vec4 offset */
- instr->deref.off = regid(off, chan);
- }
+ instr->address = ctx->block->address;
}
reg = ir3_reg_create(instr, regid(num, chan), flags);
-
- if (src->Indirect && (src->File != TGSI_FILE_CONSTANT)) {
- unsigned aid = src_array_id(ctx, src);
- reg->size = 4 * (1 + ctx->array[aid].last - ctx->array[aid].first);
- } else {
- reg->wrmask = wrmask;
- }
+ reg->wrmask = wrmask;
if (wrmask == 0x1) {
/* normal case */
@@ -872,14 +860,6 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
reg->instr = collect;
}
- if (src->Indirect) {
- unsigned size = reg->size;
-
- reg = ir3_reg_create(orig, 0, flags | IR3_REG_SSA);
- reg->instr = instr;
- reg->size = size;
- }
-
return reg;
}
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
index b70aba956c9..898ed70abeb 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
@@ -95,6 +95,9 @@ instr_cp(struct ir3_instruction *instr)
foreach_src(reg, instr)
if (reg->flags & IR3_REG_SSA)
reg->instr = instr_cp(reg->instr);
+
+ if (instr->address)
+ instr->address = instr_cp(instr->address);
}
return instr;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_dump.c b/src/gallium/drivers/freedreno/ir3/ir3_dump.c
index 42a38d7511e..a846777b879 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_dump.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_dump.c
@@ -58,9 +58,6 @@ static void dump_instr_name(struct ir3_dump_ctx *ctx,
case OPC_META_PHI:
fprintf(ctx->f, "&#934;");
break;
- case OPC_META_DEREF:
- fprintf(ctx->f, "(*)");
- break;
default:
/* shouldn't hit here.. just for debugging: */
switch (instr->opc) {
@@ -171,8 +168,7 @@ static void dump_instr(struct ir3_dump_ctx *ctx,
ir3_block_dump(ctx, instr->flow.else_block, "else");
if (reg->flags & IR3_REG_SSA)
dump_instr(ctx, reg->instr);
- } else if ((instr->opc == OPC_META_PHI) ||
- (instr->opc == OPC_META_DEREF)) {
+ } else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
ir3_instr_dump(ctx, instr);
}
@@ -234,8 +230,7 @@ static void dump_link2(struct ir3_dump_ctx *ctx,
printdef(ctx, defer, "output%lx:<out%u>:w -> %s",
PTRID(instr->inout.block),
instr->regs[0]->num, target);
- } else if ((instr->opc == OPC_META_PHI) ||
- (instr->opc == OPC_META_DEREF)) {
+ } else if (instr->opc == OPC_META_PHI) {
/* treat like a normal instruction: */
printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
}
@@ -412,6 +407,13 @@ ir3_dump_instr_single(struct ir3_instruction *instr)
dump_reg_name(&ctx, reg, !!i);
}
+ if (instr->address) {
+ fprintf(ctx.f, ", address=_");
+ fprintf(ctx.f, "[");
+ dump_instr_name(&ctx, instr->address);
+ fprintf(ctx.f, "]");
+ }
+
if (is_meta(instr) && (instr->opc == OPC_META_FO))
printf(", off=%d", instr->fo.off);
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_ra.c b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
index 03180b13b18..0f6d40f5a7c 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_ra.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
@@ -357,6 +357,11 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
static void instr_assign_src(struct ir3_ra_ctx *ctx,
struct ir3_instruction *instr, unsigned r, unsigned name)
{
+ struct ir3_register *reg = instr->regs[r];
+
+ if (reg->flags & IR3_REG_RELATIV)
+ name += reg->offset;
+
reg_assign(instr, r, name);
if (is_meta(instr)) {
@@ -372,14 +377,6 @@ static void instr_assign_src(struct ir3_ra_ctx *ctx,
case OPC_META_FI:
instr_assign(ctx, instr, name - (r - 1));
return;
- case OPC_META_DEREF:
- /* first arg of meta:deref is the addr reg (do not
- * propagate), 2nd is actual src (fanin) which does
- * get propagated)
- */
- if (r == 2)
- instr_assign(ctx, instr, name + instr->deref.off);
- break;
default:
break;
}
@@ -392,6 +389,9 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
struct ir3_instruction *n, *src;
struct ir3_register *reg = instr->regs[0];
+ if ((reg->flags & IR3_REG_RELATIV))
+ name += reg->offset;
+
/* check if already assigned: */
if (!(reg->flags & IR3_REG_SSA)) {
/* ... and if so, sanity check: */
@@ -484,9 +484,6 @@ static void instr_alloc_and_assign(struct ir3_ra_ctx *ctx,
/* allocate register(s): */
if (name >= 0) {
/* already partially assigned, just finish the job */
- } else if (is_addr(instr)) {
- debug_assert(!instr->cp.right);
- name = instr->regs[2]->num + instr->deref.off;
} else if (reg_gpr(dst)) {
int size;
/* number of consecutive registers to assign: */
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
index 1288452d29d..909ecc23449 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
@@ -292,16 +292,7 @@ static struct ir3_instruction * reverse(struct ir3_instruction *instr)
static bool uses_current_addr(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
- struct ir3_instruction *src;
- foreach_ssa_src(src, instr) {
- if (is_addr(src)) {
- struct ir3_instruction *addr =
- src->regs[1]->instr; /* the mova */
- if (ctx->addr == addr)
- return true;
- }
- }
- return false;
+ return instr->address && (ctx->addr == instr->address);
}
static bool uses_current_pred(struct ir3_sched_ctx *ctx,