#include "fd3_compiler.h"
#include "fd3_program.h"
-#include "fd3_util.h"
#include "instr-a3xx.h"
#include "ir3.h"
-/* NOTE on half/full precision:
- * Currently, the front end (ie. basically this file) does everything in
- * full precision (with the exception of trans_arl() which doesn't work
- * currently.. we reject anything with relative addressing and fallback
- * to old compiler).
- *
- * In the RA step, if half_precision, it will assign the output to hr0.x
- * but use full precision everywhere else.
- *
- * Eventually we'll need a better way to communicate type information
- * to RA so that it can more properly assign both half and full precision
- * registers. (And presumably double precision pairs for a4xx?) This
- * would let us make more use of half precision registers, while still
- * keeping things like tex coords in full precision registers.
- *
- * Since the RA is dealing with patching instruction types for half
- * precision output, we can ignore that in the front end and just always
- * create full precision instructions.
- */
-
struct fd3_compile_context {
const struct tgsi_token *tokens;
bool free_tokens;
return (instr->category == -1);
}
-static inline bool is_deref(struct ir3_instruction *instr)
+static inline bool is_addr(struct ir3_instruction *instr)
{
return is_meta(instr) && (instr->opc == OPC_META_DEREF);
}
return false;
}
-/* TODO combine is_gpr()/reg_gpr().. */
static inline bool reg_gpr(struct ir3_register *r)
{
if (r->flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_RELATIV | IR3_REG_SSA | IR3_REG_ADDR))
struct ir3_sched_ctx {
struct ir3_instruction *scheduled; /* last scheduled instr */
- struct ir3_instruction *deref; /* current deref, if any */
+ struct ir3_instruction *addr; /* current a0.x user, if any */
unsigned cnt;
};
}
if (writes_addr(instr)) {
- assert(ctx->deref == NULL);
- ctx->deref = instr;
+ assert(ctx->addr == NULL);
+ ctx->addr = instr;
}
instr->flags |= IR3_INSTR_MARK;
/* if this is a write to address register, and addr register
* is currently in use, we need to defer until it is free:
*/
- if (writes_addr(instr) && ctx->deref) {
- assert(ctx->deref != instr);
+ if (writes_addr(instr) && ctx->addr) {
+ assert(ctx->addr != instr);
return DELAYED;
}
return reversed;
}
-static bool uses_current_deref(struct ir3_sched_ctx *ctx,
+static bool uses_current_addr(struct ir3_sched_ctx *ctx,
struct ir3_instruction *instr)
{
unsigned i;
for (i = 1; i < instr->regs_count; i++) {
struct ir3_register *reg = instr->regs[i];
if (reg->flags & IR3_REG_SSA) {
- if (is_deref(reg->instr)) {
- struct ir3_instruction *deref;
- deref = reg->instr->regs[1]->instr; /* the mova */
- if (ctx->deref == deref)
+ if (is_addr(reg->instr)) {
+ struct ir3_instruction *addr;
+ addr = reg->instr->regs[1]->instr; /* the mova */
+ if (ctx->addr == addr)
return true;
}
}
struct ir3_block *block)
{
struct ir3_instruction *instr = block->head;
- bool in_use = false;
+ bool addr_in_use = false;
unsigned cnt = ~0;
while (instr) {
struct ir3_instruction *next = instr->next;
+ bool addr = uses_current_addr(ctx, instr);
- if (uses_current_deref(ctx, instr)) {
+ if (addr) {
int ret = trysched(ctx, instr);
if (ret == SCHEDULED)
cnt = 0;
else if (ret > 0)
cnt = MIN2(cnt, ret);
- in_use = true;
+ if (addr)
+ addr_in_use = true;
}
instr = next;
}
- if (!in_use)
- ctx->deref = NULL;
+ if (!addr_in_use)
+ ctx->addr = NULL;
return cnt;
}