int unit;
bool has_constants;
- uint32_t constants[4];
+ midgard_constants constants;
uint16_t inline_constant;
bool has_blend_constant;
bool has_inline_constant;
int padding;
int control;
bool has_embedded_constants;
- float constants[4];
+ midgard_constants constants;
bool has_blend_constant;
bool last_writeout;
} midgard_bundle;
.no_spill = (1 << REG_CLASS_WORK)
};
- ins.constants[0] = byte;
+ ins.constants.u32[0] = byte;
if (is_store) {
ins.src[0] = srcdest;
}
midgard_texture_word;
+/* Up to 16 constant bytes can be embedded in a bundle. This union describes
+ * all possible layouts.
+ */
+
+typedef union midgard_constants {
+ double f64[2];
+ uint64_t u64[2];
+ int64_t i64[2];
+ float f32[4];
+ uint32_t u32[4];
+ int32_t i32[4];
+ uint16_t f16[8];
+ uint16_t u16[8];
+ int16_t i16[8];
+ uint8_t u8[16];
+ int8_t i8[16];
+}
+midgard_constants;
+
#endif
{
nir_ssa_def def = instr->def;
- float *v = rzalloc_array(NULL, float, 4);
- nir_const_value_to_array(v, instr->value, instr->def.num_components, f32);
+ midgard_constants *consts = rzalloc(NULL, midgard_constants);
+
+ assert(instr->def.num_components * instr->def.bit_size <= sizeof(*consts) * 8);
+
+#define RAW_CONST_COPY(bits) \
+ nir_const_value_to_array(consts->u##bits, instr->value, \
+ instr->def.num_components, u##bits)
+
+ switch (instr->def.bit_size) {
+ case 64:
+ RAW_CONST_COPY(64);
+ break;
+ case 32:
+ RAW_CONST_COPY(32);
+ break;
+ case 16:
+ RAW_CONST_COPY(16);
+ break;
+ case 8:
+ RAW_CONST_COPY(8);
+ break;
+ default:
+ unreachable("Invalid bit_size for load_const instruction\n");
+ }
/* Shifted for SSA, +1 for off-by-one */
- _mesa_hash_table_u64_insert(ctx->ssa_constants, (def.index << 1) + 1, v);
+ _mesa_hash_table_u64_insert(ctx->ssa_constants, (def.index << 1) + 1, consts);
}
/* Normally constants are embedded implicitly, but for I/O and such we have to
ins.src[1] = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
ins.has_constants = true;
- if (instr->op == nir_op_b2f32) {
- float f = 1.0f;
- memcpy(&ins.constants, &f, sizeof(float));
- } else {
- ins.constants[0] = 1;
- }
-
+ if (instr->op == nir_op_b2f32)
+ ins.constants.f32[0] = 1.0f;
+ else
+ ins.constants.i32[0] = 1;
for (unsigned c = 0; c < 16; ++c)
ins.swizzle[1][c] = 0;
ins.has_inline_constant = false;
ins.src[1] = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
ins.has_constants = true;
- ins.constants[0] = 0;
+ ins.constants.u32[0] = 0;
for (unsigned c = 0; c < 16; ++c)
ins.swizzle[1][c] = 0;
/* TODO: half-floats */
midgard_instruction ins = m_ld_ubo_int4(dest, 0);
- ins.constants[0] = offset;
+ ins.constants.u32[0] = offset;
if (instr->type == nir_instr_type_intrinsic)
mir_set_intr_mask(instr, &ins, true);
/* Add dependencies */
ins.src[0] = src;
- ins.constants[0] = rt * 0x100;
+ ins.constants.u32[0] = rt * 0x100;
/* Emit the branch */
midgard_instruction *br = emit_mir_instruction(ctx, ins);
/* Scale constant appropriately, if we can legally */
uint16_t scaled_constant = 0;
- if (midgard_is_integer_op(op) || is_16) {
- unsigned int *iconstants = (unsigned int *) ins->constants;
- scaled_constant = (uint16_t) iconstants[component];
+ if (is_16) {
+ scaled_constant = ins->constants.u16[component];
+ } else if (midgard_is_integer_op(op)) {
+ scaled_constant = ins->constants.u32[component];
/* Constant overflow after resize */
- if (scaled_constant != iconstants[component])
+ if (scaled_constant != ins->constants.u32[component])
continue;
} else {
- float *f = (float *) ins->constants;
- float original = f[component];
+ float original = ins->constants.f32[component];
scaled_constant = _mesa_float_to_half(original);
/* Check for loss of precision. If this is
/* Make sure that the constant is not itself a vector
* by checking if all accessed values are the same. */
- uint32_t *cons = ins->constants;
- uint32_t value = cons[component];
+ const midgard_constants *cons = &ins->constants;
+ uint32_t value = is_16 ? cons->u16[component] : cons->u32[component];
bool is_vector = false;
unsigned mask = effective_writemask(&ins->alu, ins->mask);
if (!(mask & (1 << c)))
continue;
- uint32_t test = cons[ins->swizzle[1][c]];
+ uint32_t test = is_16 ?
+ cons->u16[ins->swizzle[1][c]] :
+ cons->u32[ins->swizzle[1][c]];
if (test != value) {
is_vector = true;
struct midgard_instruction ins = v_branch(false, false);
ins.writeout = true;
ins.branch.target_block = ctx->block_count - 1;
- ins.constants[0] = rt * 0x100;
+ ins.constants.u32[0] = rt * 0x100;
emit_mir_instruction(ctx, ins);
ctx->current_block->epilogue = true;
/* Tack on constants */
- if (bundle->has_embedded_constants) {
- util_dynarray_append(emission, float, bundle->constants[0]);
- util_dynarray_append(emission, float, bundle->constants[1]);
- util_dynarray_append(emission, float, bundle->constants[2]);
- util_dynarray_append(emission, float, bundle->constants[3]);
- }
+ if (bundle->has_embedded_constants)
+ util_dynarray_append(emission, midgard_constants, bundle->constants);
}
/* Shift applied to the immediate used as an offset. Probably this is papering
mir_pack_swizzle_ldst(bundle->instructions[i]);
/* Apply a constant offset */
- unsigned offset = bundle->instructions[i]->constants[0];
+ unsigned offset = bundle->instructions[i]->constants.u32[0];
if (offset) {
unsigned shift = mir_ldst_imm_shift(bundle->instructions[i]->load_store.op);
/* We found an imov with a constant. Check the constants */
bool ok = true;
- for (unsigned i = 0; i < ARRAY_SIZE(ins->constants); ++i)
- ok &= mir_constant_float(ins->constants[i]);
+ for (unsigned i = 0; i < ARRAY_SIZE(ins->constants.u32); ++i)
+ ok &= mir_constant_float(ins->constants.u32[i]);
if (!ok)
continue;
mir_print_swizzle(ins->swizzle[3]);
if (ins->has_constants) {
- uint32_t *uc = ins->constants;
- float *fc = (float *) uc;
+ uint32_t *uc = ins->constants.u32;
+ float *fc = ins->constants.f32;
if (midgard_is_integer_op(ins->alu.op))
printf(" <0x%X, 0x%X, 0x%X, 0x%x>", uc[0], uc[1], uc[2], uc[3]);
* mode, the constants array will be updated, and the instruction
* will be adjusted to index into the constants array */
- uint8_t *constants;
+ midgard_constants *constants;
unsigned constant_count;
bool blend_constant;
if (pred->constant_count)
return false;
- uint16_t *bundles = (uint16_t *) pred->constants;
- uint32_t *constants = (uint32_t *) ins->constants;
+ uint16_t *bundles = pred->constants->u16;
+ const uint16_t *constants = ins->constants.u16;
/* Copy them wholesale */
for (unsigned i = 0; i < 4; ++i)
pred->constant_count = 16;
} else {
/* Pack 32-bit constants */
- uint32_t *bundles = (uint32_t *) pred->constants;
- uint32_t *constants = (uint32_t *) ins->constants;
+ uint32_t *bundles = pred->constants->u32;
+ const uint32_t *constants = ins->constants.u32;
unsigned r_constant = SSA_FIXED_REGISTER(REGISTER_CONSTANT);
unsigned mask = mir_from_bytemask(mir_bytemask_of_read_components(ins, r_constant), midgard_reg_mode_32);
.tag = TAG_ALU_4,
.destructive = true,
.exclude = ~0,
- .constants = (uint8_t *) bundle.constants
+ .constants = &bundle.constants
};
midgard_instruction *vmul = NULL;
/* If we have a render target reference, schedule a move for it */
- if (branch && branch->writeout && (branch->constants[0] || ctx->is_blend)) {
+ if (branch && branch->writeout && (branch->constants.u32[0] || ctx->is_blend)) {
midgard_instruction mov = v_mov(~0, make_compiler_temp(ctx));
sadd = mem_dup(&mov, sizeof(midgard_instruction));
sadd->unit = UNIT_SADD;
sadd->mask = 0x1;
sadd->has_inline_constant = true;
- sadd->inline_constant = branch->constants[0];
+ sadd->inline_constant = branch->constants.u32[0];
branch->src[1] = mov.dest;
/* TODO: Don't leak */
}
return (ins->type == TAG_LOAD_STORE_4) &&
(OP_IS_UBO_READ(ins->load_store.op)) &&
- !(ins->constants[0] & 0xF) &&
+ !(ins->constants.u32[0] & 0xF) &&
!(ins->load_store.arg_1) &&
(ins->load_store.arg_2 == 0x1E) &&
- ((ins->constants[0] / 16) < 16);
+ ((ins->constants.u32[0] / 16) < 16);
}
static unsigned
mir_foreach_instr_global(ctx, ins) {
if (mir_is_promoteable_ubo(ins))
- count = MAX2(count, ins->constants[0] / 16);
+ count = MAX2(count, ins->constants.u32[0] / 16);
}
return count;
mir_foreach_instr_global_safe(ctx, ins) {
if (!mir_is_promoteable_ubo(ins)) continue;
- unsigned off = ins->constants[0];
+ unsigned off = ins->constants.u32[0];
unsigned address = off / 16;
/* Check if it's a promotable range */