unsigned mir_use_count(compiler_context *ctx, unsigned value);
uint16_t mir_bytemask_of_read_components(midgard_instruction *ins, unsigned node);
uint16_t mir_bytemask_of_read_components_index(midgard_instruction *ins, unsigned i);
-midgard_reg_mode mir_typesize(midgard_instruction *ins);
-midgard_reg_mode mir_srcsize(midgard_instruction *ins, unsigned i);
-unsigned mir_bytes_for_mode(midgard_reg_mode mode);
-midgard_reg_mode mir_mode_for_destsize(unsigned size);
-uint16_t mir_from_bytemask(uint16_t bytemask, midgard_reg_mode mode);
+uint16_t mir_from_bytemask(uint16_t bytemask, unsigned bits);
uint16_t mir_bytemask(midgard_instruction *ins);
-uint16_t mir_round_bytemask_up(uint16_t mask, midgard_reg_mode mode);
+uint16_t mir_round_bytemask_up(uint16_t mask, unsigned bits);
void mir_set_bytemask(midgard_instruction *ins, uint16_t bytemask);
unsigned mir_upper_override(midgard_instruction *ins);
if (store) { \
i.src[0] = ssa; \
i.src_types[0] = T; \
+ i.dest_type = T; \
} else { \
i.dest = ssa; \
i.dest_type = T; \
unsigned packed = 0;
if (ins->alu.reg_mode == midgard_reg_mode_64) {
- midgard_reg_mode mode = mir_srcsize(ins, i);
- unsigned components = 16 / mir_bytes_for_mode(mode);
+ unsigned sz = nir_alu_type_get_type_size(ins->src_types[i]);
+ unsigned components = 64 / sz;
packed = mir_pack_swizzle_64(ins->swizzle[i], components);
- if (mode == midgard_reg_mode_32) {
+ if (sz == 32) {
bool lo = ins->swizzle[i][0] >= COMPONENT_Z;
bool hi = ins->swizzle[i][1] >= COMPONENT_Z;
unsigned mask = mir_bytemask(ins);
} else {
src[i].rep_low |= hi;
}
- } else if (mode < midgard_reg_mode_32) {
+ } else if (sz < 32) {
unreachable("Cannot encode 8/16 swizzle in 64-bit");
}
} else {
bool upper = ins->swizzle[i][first] > 3;
if (upper && ins->mask)
- assert(mir_srcsize(ins, i) <= midgard_reg_mode_16);
+ assert(nir_alu_type_get_type_size(ins->src_types[i]) <= 16);
for (unsigned c = 0; c < 4; ++c) {
unsigned v = ins->swizzle[i][c];
static void
mir_pack_ldst_mask(midgard_instruction *ins)
{
- midgard_reg_mode mode = mir_typesize(ins);
+ unsigned sz = nir_alu_type_get_type_size(ins->dest_type);
unsigned packed = ins->mask;
- if (mode == midgard_reg_mode_64) {
+ if (sz == 64) {
packed = ((ins->mask & 0x2) ? (0x8 | 0x4) : 0) |
((ins->mask & 0x1) ? (0x2 | 0x1) : 0);
- } else if (mode == midgard_reg_mode_16) {
+ } else if (sz == 16) {
packed = 0;
for (unsigned i = 0; i < 4; ++i) {
packed |= (u << i);
}
+ } else {
+ assert(sz == 32);
}
ins->load_store.mask = packed;
mir_foreach_instr_in_block_rev(block, ins) {
if (can_cull_mask(ctx, ins)) {
- midgard_reg_mode mode = mir_typesize(ins);
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
unsigned oldmask = ins->mask;
- unsigned rounded = mir_round_bytemask_up(live[ins->dest], mode);
- unsigned cmask = mir_from_bytemask(rounded, mode);
+ unsigned rounded = mir_round_bytemask_up(live[ins->dest], type_size);
+ unsigned cmask = mir_from_bytemask(rounded, type_size);
ins->mask &= cmask;
progress |= (ins->mask != oldmask);
static void
mir_print_embedded_constant(midgard_instruction *ins, unsigned src_idx)
{
- unsigned type_size = mir_bytes_for_mode(ins->alu.reg_mode);
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
midgard_vector_alu_src src;
assert(src_idx <= 1);
unsigned *swizzle = ins->swizzle[src_idx];
unsigned comp_mask = effective_writemask(&ins->alu, ins->mask);
unsigned num_comp = util_bitcount(comp_mask);
- unsigned max_comp = 16 / type_size;
+ unsigned max_comp = 64 / type_size;
bool first = true;
printf("#");
/* Shift up by reg_offset and horizontally by dst_offset. */
static void
-offset_swizzle(unsigned *swizzle, unsigned reg_offset, unsigned srcsize, unsigned dst_offset)
+offset_swizzle(unsigned *swizzle, unsigned reg_offset, unsigned srcsize, unsigned dstsize, unsigned dst_offset)
{
unsigned out[MIR_VEC_COMPONENTS];
signed reg_comp = reg_offset / srcsize;
- signed dst_comp = dst_offset / srcsize;
+ signed dst_comp = dst_offset / dstsize;
unsigned max_component = (16 / srcsize) - 1;
assert(reg_comp * srcsize == reg_offset);
- assert(dst_comp * srcsize == dst_offset);
+ assert(dst_comp * dstsize == dst_offset);
for (signed c = 0; c < MIR_VEC_COMPONENTS; ++c) {
signed comp = MAX2(c - dst_comp, 0);
/* Helper to return the default phys_reg for a given register */
static struct phys_reg
-default_phys_reg(int reg, midgard_reg_mode size)
+default_phys_reg(int reg, unsigned size)
{
struct phys_reg r = {
.reg = reg,
.offset = 0,
- .size = mir_bytes_for_mode(size)
+ .size = size
};
return r;
* register corresponds to */
static struct phys_reg
-index_to_reg(compiler_context *ctx, struct lcra_state *l, unsigned reg, midgard_reg_mode size)
+index_to_reg(compiler_context *ctx, struct lcra_state *l, unsigned reg, unsigned size)
{
/* Check for special cases */
if (reg == ~0)
struct phys_reg r = {
.reg = l->solutions[reg] / 16,
.offset = l->solutions[reg] & 0xF,
- .size = mir_bytes_for_mode(size)
+ .size = size
};
/* Report that we actually use this register, and return it */
} else {
idx = spill_idx++;
m = v_mov(i, idx);
- m.mask = mir_from_bytemask(mir_bytemask_of_read_components(pre_use, i), midgard_reg_mode_32);
+ m.mask = mir_from_bytemask(mir_bytemask_of_read_components(pre_use, i), 32);
mir_insert_instruction_before(ctx, pre_use, m);
mir_rewrite_index_src_single(pre_use, i, idx);
}
if (ins->type == TAG_LOAD_STORE_4 && OP_HAS_ADDRESS(ins->load_store.op)) {
mir_foreach_src(ins, v) {
unsigned s = ins->src[v];
- unsigned size = mir_srcsize(ins, v);
+ unsigned size = nir_alu_type_get_type_size(ins->src_types[v]);
if (s < ctx->temp_count)
- min_alignment[s] = (size == midgard_reg_mode_64) ? 3 : 2;
+ min_alignment[s] = (size == 64) ? 3 : 2;
}
}
struct lcra_state *l,
midgard_instruction *ins)
{
+ unsigned src_size[MIR_SRC_COUNT];
+
+ for (unsigned i = 0; i < MIR_SRC_COUNT; ++i)
+ src_size[i] = MAX2(nir_alu_type_get_type_size(ins->src_types[i]) / 8, 1);
+
+ unsigned dest_size = MAX2(nir_alu_type_get_type_size(ins->dest_type) / 8, 1);
+
switch (ins->type) {
case TAG_ALU_4:
case TAG_ALU_8:
if (ins->compact_branch)
return;
- struct phys_reg src1 = index_to_reg(ctx, l, ins->src[0], mir_srcsize(ins, 0));
- struct phys_reg src2 = index_to_reg(ctx, l, ins->src[1], mir_srcsize(ins, 1));
- struct phys_reg dest = index_to_reg(ctx, l, ins->dest, mir_typesize(ins));
+ struct phys_reg src1 = index_to_reg(ctx, l, ins->src[0], src_size[0]);
+ struct phys_reg src2 = index_to_reg(ctx, l, ins->src[1], src_size[1]);
+ struct phys_reg dest = index_to_reg(ctx, l, ins->dest, dest_size);
mir_set_bytemask(ins, mir_bytemask(ins) << dest.offset);
GET_CHANNEL_COUNT(alu_opcode_props[ins->alu.op].props) ? 0 :
dest.offset;
- offset_swizzle(ins->swizzle[0], src1.offset, src1.size, dest_offset);
+ offset_swizzle(ins->swizzle[0], src1.offset, src1.size, dest.size, dest_offset);
ins->registers.src1_reg = src1.reg;
} else {
midgard_vector_alu_src mod2 =
vector_alu_from_unsigned(ins->alu.src2);
- offset_swizzle(ins->swizzle[1], src2.offset, src2.size, dest_offset);
+ offset_swizzle(ins->swizzle[1], src2.offset, src2.size, dest.size, dest_offset);
ins->alu.src2 = vector_alu_srco_unsigned(mod2);
ins->registers.src2_reg = src2.reg;
bool encodes_src = OP_IS_STORE(ins->load_store.op);
if (encodes_src) {
- struct phys_reg src = index_to_reg(ctx, l, ins->src[0], mir_srcsize(ins, 0));
+ struct phys_reg src = index_to_reg(ctx, l, ins->src[0], src_size[0]);
assert(src.reg == 26 || src.reg == 27);
ins->load_store.reg = src.reg - 26;
- offset_swizzle(ins->swizzle[0], src.offset, src.size, 0);
+ offset_swizzle(ins->swizzle[0], src.offset, src.size, 1, 0);
} else {
- struct phys_reg dst = index_to_reg(ctx, l, ins->dest, mir_typesize(ins));
+ struct phys_reg dst = index_to_reg(ctx, l, ins->dest, dest_size);
ins->load_store.reg = dst.reg;
- offset_swizzle(ins->swizzle[0], 0, 4, dst.offset);
+ offset_swizzle(ins->swizzle[0], 0, 4, dst.size, dst.offset);
mir_set_bytemask(ins, mir_bytemask(ins) << dst.offset);
}
unsigned src2 = ins->src[1];
unsigned src3 = ins->src[2];
- midgard_reg_mode m32 = midgard_reg_mode_32;
if (src2 != ~0) {
- struct phys_reg src = index_to_reg(ctx, l, src2, m32);
+ struct phys_reg src = index_to_reg(ctx, l, src2, 4);
unsigned component = src.offset / src.size;
assert(component * src.size == src.offset);
ins->load_store.arg_1 |= midgard_ldst_reg(src.reg, component);
}
if (src3 != ~0) {
- struct phys_reg src = index_to_reg(ctx, l, src3, m32);
+ struct phys_reg src = index_to_reg(ctx, l, src3, 4);
unsigned component = src.offset / src.size;
assert(component * src.size == src.offset);
ins->load_store.arg_2 |= midgard_ldst_reg(src.reg, component);
break;
/* Grab RA results */
- struct phys_reg dest = index_to_reg(ctx, l, ins->dest, mir_typesize(ins));
- struct phys_reg coord = index_to_reg(ctx, l, ins->src[1], mir_srcsize(ins, 1));
- struct phys_reg lod = index_to_reg(ctx, l, ins->src[2], mir_srcsize(ins, 2));
- struct phys_reg offset = index_to_reg(ctx, l, ins->src[3], mir_srcsize(ins, 2));
+ struct phys_reg dest = index_to_reg(ctx, l, ins->dest, dest_size);
+ struct phys_reg coord = index_to_reg(ctx, l, ins->src[1], src_size[1]);
+ struct phys_reg lod = index_to_reg(ctx, l, ins->src[2], src_size[2]);
+ struct phys_reg offset = index_to_reg(ctx, l, ins->src[3], src_size[3]);
/* First, install the texture coordinate */
ins->texture.in_reg_full = 1;
ins->texture.in_reg_upper = 0;
ins->texture.in_reg_select = coord.reg & 1;
- offset_swizzle(ins->swizzle[1], coord.offset, coord.size, 0);
+ offset_swizzle(ins->swizzle[1], coord.offset, coord.size, dest.size, 0);
/* Next, install the destination */
ins->texture.out_full = 1;
ins->texture.out_upper = 0;
ins->texture.out_reg_select = dest.reg & 1;
- offset_swizzle(ins->swizzle[0], 0, 4, dest.offset);
+ offset_swizzle(ins->swizzle[0], 0, 4, dest.size, dest.offset);
mir_set_bytemask(ins, mir_bytemask(ins) << dest.offset);
/* If there is a register LOD/bias, use it */
/* Mask the load based on the component count
* actually needed to prevent RA loops */
- st.mask = mir_from_bytemask(read_bytemask, midgard_reg_mode_32);
+ st.mask = mir_from_bytemask(read_bytemask, 32);
mir_insert_instruction_before_scheduled(ctx, block, before, st);
} else {
return true;
unsigned r_constant = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
- midgard_reg_mode dst_mode = mir_typesize(ins);
-
unsigned bundle_constant_mask = pred->constant_mask;
unsigned comp_mapping[2][16] = { };
uint8_t bundle_constants[16];
if (ins->src[src] != SSA_FIXED_REGISTER(REGISTER_CONSTANT))
continue;
- midgard_reg_mode src_mode = mir_srcsize(ins, src);
- unsigned type_size = mir_bytes_for_mode(src_mode);
+ unsigned type_size = nir_alu_type_get_type_size(ins->src_types[src]) / 8;
unsigned max_comp = 16 / type_size;
unsigned comp_mask = mir_from_bytemask(mir_round_bytemask_up(
mir_bytemask_of_read_components_index(ins, src),
- dst_mode),
- dst_mode);
+ type_size * 8),
+ type_size * 8);
unsigned type_mask = (1 << type_size) - 1;
for (unsigned comp = 0; comp < max_comp; comp++) {
return mod != midgard_outmod_none;
}
-/* Grabs the type size. */
-
-midgard_reg_mode
-mir_typesize(midgard_instruction *ins)
-{
- if (ins->compact_branch)
- return midgard_reg_mode_32;
-
- /* TODO: Type sizes for texture */
- if (ins->type == TAG_TEXTURE_4)
- return midgard_reg_mode_32;
-
- if (ins->type == TAG_LOAD_STORE_4)
- return GET_LDST_SIZE(load_store_opcode_props[ins->load_store.op].props);
-
- if (ins->type == TAG_ALU_4) {
- midgard_reg_mode mode = ins->alu.reg_mode;
-
- /* If we have an override, step down by half */
- if (ins->alu.dest_override != midgard_dest_override_none) {
- assert(mode > midgard_reg_mode_8);
- mode--;
- }
-
- return mode;
- }
-
- unreachable("Invalid instruction type");
-}
-
-/* Grabs the size of a source */
-
-midgard_reg_mode
-mir_srcsize(midgard_instruction *ins, unsigned i)
-{
- if (ins->type == TAG_LOAD_STORE_4) {
- if (OP_HAS_ADDRESS(ins->load_store.op)) {
- if (i == 1)
- return midgard_reg_mode_64;
- else if (i == 2) {
- bool zext = ins->load_store.arg_1 & 0x80;
- return zext ? midgard_reg_mode_32 : midgard_reg_mode_64;
- }
- }
- }
-
- /* TODO: 16-bit textures/ldst */
- if (ins->type == TAG_TEXTURE_4 || ins->type == TAG_LOAD_STORE_4)
- return midgard_reg_mode_32;
-
- /* TODO: 16-bit branches */
- if (ins->compact_branch)
- return midgard_reg_mode_32;
-
- if (i >= 2) {
- /* TODO: 16-bit conditions, ffma */
- return midgard_reg_mode_32;
- }
-
- /* Default to type of the instruction */
-
- midgard_reg_mode mode = ins->alu.reg_mode;
-
- /* If we have a half modifier, step down by half */
-
- if ((mir_get_alu_src(ins, i)).half) {
- assert(mode > midgard_reg_mode_8);
- mode--;
- }
-
- return mode;
-}
-
-midgard_reg_mode
-mir_mode_for_destsize(unsigned size)
-{
- switch (size) {
- case 8:
- return midgard_reg_mode_8;
- case 16:
- return midgard_reg_mode_16;
- case 32:
- return midgard_reg_mode_32;
- case 64:
- return midgard_reg_mode_64;
- default:
- unreachable("Unknown destination size");
- }
-}
-
-/* ...and the inverse */
-
-unsigned
-mir_bytes_for_mode(midgard_reg_mode mode)
-{
- switch (mode) {
- case midgard_reg_mode_8:
- return 1;
- case midgard_reg_mode_16:
- return 2;
- case midgard_reg_mode_32:
- return 4;
- case midgard_reg_mode_64:
- return 8;
- default:
- unreachable("Invalid register mode");
- }
-}
-
uint16_t
-mir_from_bytemask(uint16_t bytemask, midgard_reg_mode mode)
+mir_from_bytemask(uint16_t bytemask, unsigned bits)
{
unsigned value = 0;
- unsigned count = mir_bytes_for_mode(mode);
+ unsigned count = bits / 8;
for (unsigned c = 0, d = 0; c < 16; c += count, ++d) {
bool a = (bytemask & (1 << c)) != 0;
* component, and check if any bytes in the component are masked on */
uint16_t
-mir_round_bytemask_up(uint16_t mask, midgard_reg_mode mode)
+mir_round_bytemask_up(uint16_t mask, unsigned bits)
{
- unsigned bytes = mir_bytes_for_mode(mode);
+ unsigned bytes = bits / 8;
unsigned maxmask = mask_of(bytes);
unsigned channels = 16 / bytes;
uint16_t
mir_bytemask(midgard_instruction *ins)
{
- return pan_to_bytemask(mir_bytes_for_mode(mir_typesize(ins)) * 8, ins->mask);
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
+ return pan_to_bytemask(type_size, ins->mask);
}
void
mir_set_bytemask(midgard_instruction *ins, uint16_t bytemask)
{
- ins->mask = mir_from_bytemask(bytemask, mir_typesize(ins));
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
+ ins->mask = mir_from_bytemask(bytemask, type_size);
}
/* Checks if we should use an upper destination override, rather than the lower
/* Make sure we didn't already lower somehow */
assert(ins->alu.dest_override == midgard_dest_override_lower);
- /* What is the mask in terms of currently? */
- midgard_reg_mode type = mir_typesize(ins);
-
/* There are 16 bytes per vector, so there are (16/bytes)
* components per vector. So the magic half is half of
- * (16/bytes), which simplifies to 8/bytes */
+ * (16/bytes), which simplifies to 8/bytes = 8 / (bits / 8) = 64 / bits
+ * */
- unsigned threshold = 8 / mir_bytes_for_mode(type);
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
+ unsigned threshold = 64 / type_size;
/* How many components did we shift over? */
unsigned zeroes = __builtin_ctz(ins->mask);
*/
static uint16_t
-mir_bytemask_of_read_components_single(unsigned *swizzle, unsigned inmask, midgard_reg_mode mode)
+mir_bytemask_of_read_components_single(unsigned *swizzle, unsigned inmask, unsigned bits)
{
unsigned cmask = 0;
cmask |= (1 << swizzle[c]);
}
- return pan_to_bytemask(mir_bytes_for_mode(mode) * 8, cmask);
+ return pan_to_bytemask(bits, cmask);
}
uint16_t
qmask = mask_of(channel_override);
}
- return mir_bytemask_of_read_components_single(ins->swizzle[i], qmask, mir_srcsize(ins, i));
+ return mir_bytemask_of_read_components_single(ins->swizzle[i], qmask,
+ nir_alu_type_get_type_size(ins->src_types[i]));
}
uint16_t
if (ins->load_64)
mov.alu.reg_mode = midgard_reg_mode_64;
- uint16_t rounded = mir_round_bytemask_up(mir_bytemask(ins), mov.alu.reg_mode);
+ unsigned type_size = nir_alu_type_get_type_size(ins->dest_type);
+ uint16_t rounded = mir_round_bytemask_up(mir_bytemask(ins), type_size);
mir_set_bytemask(&mov, rounded);
mir_insert_instruction_before(ctx, ins, mov);
} else {
pan_to_bytemask(unsigned bytes, unsigned mask)
{
switch (bytes) {
+ case 0:
+ assert(mask == 0);
+ return 0;
+
case 8:
return mask;