From dddfe6c21ee92f015b78060545f08239c331ceba Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 2 Jan 2015 13:44:26 -0500 Subject: [PATCH] freedreno/ir3: regmask support for relative addr For temp arrays, a 32bit mask won't be sufficient.. but otoh we don't need to support an arbitrary mask. So for this case use a simple size field rather than a bitmask. Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/ir3/ir3.h | 66 +++++++++++++++----- src/gallium/drivers/freedreno/ir3/ir3_dump.c | 2 +- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index ad1e730ad4c..bd0c0a5b693 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -91,12 +91,19 @@ struct ir3_register { struct ir3_instruction *instr; }; - /* used for cat5 instructions, but also for internal/IR level - * tracking of what registers are read/written by an instruction. - * wrmask may be a bad name since it is used to represent both - * src and dst that touch multiple adjacent registers. - */ - int wrmask; + union { + /* used for cat5 instructions, but also for internal/IR level + * tracking of what registers are read/written by an instruction. + * wrmask may be a bad name since it is used to represent both + * src and dst that touch multiple adjacent registers. + */ + unsigned wrmask; + /* for relative addressing, 32bits for array size is too small, + * but otoh we don't need to deal with disjoint sets, so instead + * use a simple size field (number of scalar components). + */ + unsigned size; + }; }; #define IR3_INSTR_SRCS 10 @@ -477,10 +484,23 @@ static inline void regmask_init(regmask_t *regmask) static inline void regmask_set(regmask_t *regmask, struct ir3_register *reg) { unsigned idx = regmask_idx(reg); - unsigned i; - for (i = 0; i < IR3_INSTR_SRCS; i++, idx++) - if (reg->wrmask & (1 << i)) + if (reg->flags & IR3_REG_RELATIV) { + unsigned i; + for (i = 0; i < reg->size; i++, idx++) (*regmask)[idx / 8] |= 1 << (idx % 8); + } else { + unsigned mask; + for (mask = reg->wrmask; mask; mask >>= 1, idx++) + if (mask & 1) + (*regmask)[idx / 8] |= 1 << (idx % 8); + } +} + +static inline void regmask_or(regmask_t *dst, regmask_t *a, regmask_t *b) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE(*dst); i++) + (*dst)[i] = (*a)[i] | (*b)[i]; } /* set bits in a if not set in b, conceptually: @@ -490,22 +510,36 @@ static inline void regmask_set_if_not(regmask_t *a, struct ir3_register *reg, regmask_t *b) { unsigned idx = regmask_idx(reg); - unsigned i; - for (i = 0; i < IR3_INSTR_SRCS; i++, idx++) - if (reg->wrmask & (1 << i)) + if (reg->flags & IR3_REG_RELATIV) { + unsigned i; + for (i = 0; i < reg->size; i++, idx++) if (!((*b)[idx / 8] & (1 << (idx % 8)))) (*a)[idx / 8] |= 1 << (idx % 8); + } else { + unsigned mask; + for (mask = reg->wrmask; mask; mask >>= 1, idx++) + if (mask & 1) + if (!((*b)[idx / 8] & (1 << (idx % 8)))) + (*a)[idx / 8] |= 1 << (idx % 8); + } } -static inline unsigned regmask_get(regmask_t *regmask, +static inline bool regmask_get(regmask_t *regmask, struct ir3_register *reg) { unsigned idx = regmask_idx(reg); - unsigned i; - for (i = 0; i < IR3_INSTR_SRCS; i++, idx++) - if (reg->wrmask & (1 << i)) + if (reg->flags & IR3_REG_RELATIV) { + unsigned i; + for (i = 0; i < reg->size; i++, idx++) if ((*regmask)[idx / 8] & (1 << (idx % 8))) return true; + } else { + unsigned mask; + for (mask = reg->wrmask; mask; mask >>= 1, idx++) + if (mask & 1) + if ((*regmask)[idx / 8] & (1 << (idx % 8))) + return true; + } return false; } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_dump.c b/src/gallium/drivers/freedreno/ir3/ir3_dump.c index 60be64c0e5a..e4a13f9b4b8 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_dump.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_dump.c @@ -134,7 +134,7 @@ static void dump_reg_name(struct ir3_dump_ctx *ctx, if (reg->flags & IR3_REG_CONST) fprintf(ctx->f, "c", reg->num); else - fprintf(ctx->f, "\x1b[0;31mr\x1b[0m", reg->num); + fprintf(ctx->f, "\x1b[0;31mr\x1b[0m (%u)", reg->num, reg->size); } else { if (reg->flags & IR3_REG_HALF) fprintf(ctx->f, "h");