void mir_rewrite_index_src_single(midgard_instruction *ins, unsigned old, unsigned new);
void mir_rewrite_index_src_swizzle(compiler_context *ctx, unsigned old, unsigned new, unsigned *swizzle);
bool mir_single_use(compiler_context *ctx, unsigned value);
-bool mir_special_index(compiler_context *ctx, unsigned idx);
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);
return mod != midgard_outmod_none;
}
-/* Checks if an index will be used as a special register -- basically, if we're
- * used as the input to a non-ALU op */
-
-bool
-mir_special_index(compiler_context *ctx, unsigned idx)
-{
- mir_foreach_instr_global(ctx, ins) {
- bool is_ldst = ins->type == TAG_LOAD_STORE_4;
- bool is_tex = ins->type == TAG_TEXTURE_4;
- bool is_writeout = ins->compact_branch && ins->writeout;
-
- if (!(is_ldst || is_tex || is_writeout))
- continue;
-
- if (mir_has_arg(ins, idx))
- return true;
- }
-
- return false;
-}
-
/* Grabs the type size. */
midgard_reg_mode
return 8;
}
+/* Bitset of indices that will be used as a special register -- inputs to a
+ * non-ALU op. We precompute this set so that testing is efficient, otherwise
+ * we end up O(mn) behaviour for n instructions and m uniform reads */
+
+static BITSET_WORD *
+mir_special_indices(compiler_context *ctx)
+{
+ mir_compute_temp_count(ctx);
+ BITSET_WORD *bset = calloc(BITSET_WORDS(ctx->temp_count), sizeof(BITSET_WORD));
+
+ mir_foreach_instr_global(ctx, ins) {
+ /* Look for special instructions */
+ bool is_ldst = ins->type == TAG_LOAD_STORE_4;
+ bool is_tex = ins->type == TAG_TEXTURE_4;
+ bool is_writeout = ins->compact_branch && ins->writeout;
+
+ if (!(is_ldst || is_tex || is_writeout))
+ continue;
+
+ /* Anything read by a special instruction is itself special */
+ mir_foreach_src(ins, i) {
+ unsigned idx = ins->src[i];
+
+ if (idx < ctx->temp_count)
+ BITSET_SET(bset, idx);
+ }
+ }
+
+ return bset;
+}
+
void
midgard_promote_uniforms(compiler_context *ctx)
{
unsigned work_count = mir_work_heuristic(ctx);
unsigned promoted_count = 24 - work_count;
+ /* First, figure out special indices a priori so we don't recompute a lot */
+ BITSET_WORD *special = mir_special_indices(ctx);
+
mir_foreach_instr_global_safe(ctx, ins) {
if (!mir_is_promoteable_ubo(ins)) continue;
* we're being fed into a special class */
bool needs_move = ins->dest & PAN_IS_REG;
- needs_move |= mir_special_index(ctx, ins->dest);
+
+ if (ins->dest < ctx->temp_count)
+ needs_move |= BITSET_TEST(special, ins->dest);
if (needs_move) {
midgard_instruction mov = v_mov(promoted, ins->dest);
mir_remove_instruction(ins);
}
+
+ free(special);
}