freedreno/ir3/ra: use register_allocate

Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
Rob Clark 2015-05-01 12:21:12 -04:00
parent 694beb8b83
commit d52fb2f5ad
6 changed files with 616 additions and 507 deletions

View file

@ -83,7 +83,6 @@ struct ir3_register {
*/
IR3_REG_SSA = 0x2000, /* 'instr' is ptr to assigning instr */
IR3_REG_IA = 0x4000, /* meta-input dst is "assigned" */
IR3_REG_ADDR = 0x8000, /* register is a0.x */
} flags;
union {
/* normal registers:
@ -245,6 +244,13 @@ struct ir3_instruction {
*/
#define DEPTH_UNUSED ~0
unsigned depth;
/* When we get to the RA stage, we no longer need depth, but
* we do need instruction's position/name:
*/
struct {
uint16_t ip;
uint16_t name;
};
};
/* Used during CP and RA stages. For fanin and shader inputs/
@ -503,6 +509,28 @@ static inline bool is_mem(struct ir3_instruction *instr)
return (instr->category == 6);
}
static inline bool
is_store(struct ir3_instruction *instr)
{
if (is_mem(instr)) {
/* these instructions, the "destination" register is
* actually a source, the address to store to.
*/
switch (instr->opc) {
case OPC_STG:
case OPC_STP:
case OPC_STL:
case OPC_STLW:
case OPC_L2G:
case OPC_G2L:
return true;
default:
break;
}
}
return false;
}
static inline bool is_input(struct ir3_instruction *instr)
{
/* in some cases, ldlv is used to fetch varying without
@ -527,7 +555,7 @@ static inline bool writes_addr(struct ir3_instruction *instr)
{
if (instr->regs_count > 0) {
struct ir3_register *dst = instr->regs[0];
return !!(dst->flags & IR3_REG_ADDR);
return reg_num(dst) == REG_A0;
}
return false;
}
@ -558,7 +586,7 @@ static inline bool conflicts(struct ir3_instruction *a,
static inline bool reg_gpr(struct ir3_register *r)
{
if (r->flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_ADDR))
if (r->flags & (IR3_REG_CONST | IR3_REG_IMMED))
return false;
if ((reg_num(r) == REG_A0) || (reg_num(r) == REG_P0))
return false;
@ -771,6 +799,7 @@ void ir3_block_group(struct ir3_block *block);
int ir3_block_sched(struct ir3_block *block);
/* register assignment: */
struct ir3_ra_reg_set * ir3_ra_alloc_reg_set(void *memctx);
int ir3_block_ra(struct ir3_block *block, enum shader_t type,
bool frag_coord, bool frag_face);

View file

@ -34,6 +34,7 @@ struct ir3_compiler * ir3_compiler_create(uint32_t gpu_id)
{
struct ir3_compiler *compiler = rzalloc(NULL, struct ir3_compiler);
compiler->gpu_id = gpu_id;
compiler->set = ir3_ra_alloc_reg_set(compiler);
return compiler;
}

View file

@ -31,8 +31,11 @@
#include "ir3_shader.h"
struct ir3_ra_reg_set;
struct ir3_compiler {
uint32_t gpu_id;
struct ir3_ra_reg_set *set;
};
struct ir3_compiler * ir3_compiler_create(uint32_t gpu_id);

View file

@ -385,7 +385,8 @@ create_addr(struct ir3_block *block, struct ir3_instruction *src)
instr->regs[1]->flags |= IR3_REG_HALF;
instr = ir3_MOV(block, instr, TYPE_S16);
instr->regs[0]->flags |= IR3_REG_ADDR | IR3_REG_HALF;
instr->regs[0]->num = regid(REG_A0, 0);
instr->regs[0]->flags |= IR3_REG_HALF;
instr->regs[1]->flags |= IR3_REG_HALF;
return instr;
@ -589,6 +590,7 @@ create_frag_face(struct ir3_compile *ctx, unsigned comp)
compile_assert(ctx, !ctx->frag_face);
ctx->frag_face = create_input(block, NULL, 0);
ctx->frag_face->regs[0]->flags |= IR3_REG_HALF;
/* for faceness, we always get -1 or 0 (int).. but TGSI expects
* positive vs negative float.. and piglit further seems to
@ -1981,9 +1983,18 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
*/
if (key.half_precision) {
for (i = 0; i < block->noutputs; i++) {
if (!block->outputs[i])
struct ir3_instruction *out = block->outputs[i];
if (!out)
continue;
block->outputs[i]->regs[0]->flags |= IR3_REG_HALF;
out->regs[0]->flags |= IR3_REG_HALF;
/* output could be a fanout (ie. texture fetch output)
* in which case we need to propagate the half-reg flag
* up to the definer so that RA sees it:
*/
if (is_meta(out) && (out->opc == OPC_META_FO)) {
out = out->regs[1]->instr;
out->regs[0]->flags |= IR3_REG_HALF;
}
}
}

View file

@ -41,7 +41,7 @@ static bool is_eligible_mov(struct ir3_instruction *instr, bool allow_flags)
struct ir3_register *dst = instr->regs[0];
struct ir3_register *src = instr->regs[1];
struct ir3_instruction *src_instr = ssa(src);
if (dst->flags & (IR3_REG_ADDR | IR3_REG_RELATIV))
if (dst->flags & IR3_REG_RELATIV)
return false;
if (src->flags & IR3_REG_RELATIV)
return false;

File diff suppressed because it is too large Load diff