ir3: Make predecessors an array

We need a stable order in order to create phi instructions. In the
future we can make this more sophisticated in order to make manipulating
the CFG easier, but for now that only happens after RA, so we won't have
to worry about it.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10591>
This commit is contained in:
Connor Abbott 2021-01-29 15:31:52 +01:00 committed by Marge Bot
parent 0bd68b8386
commit dd55bd8f68
6 changed files with 56 additions and 26 deletions

View file

@ -352,10 +352,41 @@ struct ir3_block * ir3_block_create(struct ir3 *shader)
block->shader = shader;
list_inithead(&block->node);
list_inithead(&block->instr_list);
block->predecessors = _mesa_pointer_set_create(block);
return block;
}
void ir3_block_add_predecessor(struct ir3_block *block, struct ir3_block *pred)
{
array_insert(block, block->predecessors, pred);
}
void ir3_block_remove_predecessor(struct ir3_block *block, struct ir3_block *pred)
{
for (unsigned i = 0; i < block->predecessors_count; i++) {
if (block->predecessors[i] == pred) {
if (i < block->predecessors_count - 1) {
block->predecessors[i] =
block->predecessors[block->predecessors_count - 1];
}
block->predecessors_count--;
return;
}
}
}
unsigned ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pred)
{
for (unsigned i = 0; i < block->predecessors_count; i++) {
if (block->predecessors[i] == pred) {
return i;
}
}
unreachable("ir3_block_get_pred_index() invalid predecessor");
}
static struct ir3_instruction *instr_create(struct ir3_block *block, int nreg)
{
struct ir3_instruction *instr;

View file

@ -550,7 +550,7 @@ struct ir3_block {
struct ir3_instruction *condition;
struct ir3_block *successors[2];
struct set *predecessors; /* set of ir3_block */
DECLARE_ARRAY(struct ir3_block *, predecessors);
uint16_t start_ip, end_ip;
@ -579,6 +579,10 @@ block_id(struct ir3_block *block)
#endif
}
void ir3_block_add_predecessor(struct ir3_block *block, struct ir3_block *pred);
void ir3_block_remove_predecessor(struct ir3_block *block, struct ir3_block *pred);
unsigned ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pred);
struct ir3_shader_variant;
struct ir3 * ir3_create(struct ir3_compiler *compiler, struct ir3_shader_variant *v);

View file

@ -2959,7 +2959,7 @@ setup_predecessors(struct ir3 *ir)
foreach_block(block, &ir->block_list) {
for (int i = 0; i < ARRAY_SIZE(block->successors); i++) {
if (block->successors[i])
_mesa_set_add(block->successors[i]->predecessors, block);
ir3_block_add_predecessor(block->successors[i], block);
}
}
}

View file

@ -149,8 +149,8 @@ distance(struct ir3_block *block, struct ir3_instruction *instr,
/* (ab)use block->data to prevent recursion: */
block->data = block;
set_foreach (block->predecessors, entry) {
struct ir3_block *pred = (struct ir3_block *)entry->key;
for (unsigned i = 0; i < block->predecessors_count; i++) {
struct ir3_block *pred = block->predecessors[i];
unsigned n;
n = distance(pred, instr, min, pred);
@ -288,8 +288,8 @@ delay_calc_array(struct ir3_block *block, unsigned array_id,
/* (ab)use block->data to prevent recursion: */
block->data = block;
set_foreach (block->predecessors, entry) {
struct ir3_block *pred = (struct ir3_block *)entry->key;
for (unsigned i = 0; i < block->predecessors_count; i++) {
struct ir3_block *pred = block->predecessors[i];
unsigned delay =
delay_calc_array(pred, array_id, consumer, srcn, soft, pred, maxd);

View file

@ -97,8 +97,8 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
bool mergedregs = ctx->so->mergedregs;
/* our input state is the OR of all predecessor blocks' state: */
set_foreach(block->predecessors, entry) {
struct ir3_block *predecessor = (struct ir3_block *)entry->key;
for (unsigned i = 0; i < block->predecessors_count; i++) {
struct ir3_block *predecessor = block->predecessors[i];
struct ir3_legalize_block_data *pbd = predecessor->data;
struct ir3_legalize_state *pstate = &pbd->state;
@ -480,7 +480,7 @@ remove_unused_block(struct ir3_block *old_target)
for (unsigned i = 0; i < ARRAY_SIZE(old_target->successors); i++) {
if (old_target->successors[i]) {
struct ir3_block *succ = old_target->successors[i];
_mesa_set_remove_key(succ->predecessors, old_target);
ir3_block_remove_predecessor(succ, old_target);
}
}
}
@ -500,13 +500,12 @@ retarget_jump(struct ir3_instruction *instr, struct ir3_block *new_target)
}
/* update new target's predecessors: */
_mesa_set_add(new_target->predecessors, cur_block);
ir3_block_add_predecessor(new_target, cur_block);
/* and remove old_target's predecessor: */
debug_assert(_mesa_set_search(old_target->predecessors, cur_block));
_mesa_set_remove_key(old_target->predecessors, cur_block);
ir3_block_remove_predecessor(old_target, cur_block);
if (old_target->predecessors->entries == 0)
if (old_target->predecessors_count == 0)
remove_unused_block(old_target);
instr->cat0.target = new_target;
@ -588,17 +587,17 @@ static void
mark_xvergence_points(struct ir3 *ir)
{
foreach_block (block, &ir->block_list) {
if (block->predecessors->entries > 1) {
if (block->predecessors_count > 1) {
/* if a block has more than one possible predecessor, then
* the first instruction is a convergence point.
*/
mark_jp(block);
} else if (block->predecessors->entries == 1) {
} else if (block->predecessors_count == 1) {
/* If a block has one predecessor, which has multiple possible
* successors, it is a divergence point.
*/
set_foreach(block->predecessors, entry) {
struct ir3_block *predecessor = (struct ir3_block *)entry->key;
for (unsigned i = 0; i < block->predecessors_count; i++) {
struct ir3_block *predecessor = block->predecessors[i];
if (predecessor->successors[1]) {
mark_jp(block);
}

View file

@ -355,16 +355,12 @@ print_block(struct ir3_block *block, int lvl)
{
tab(lvl); printf("block%u {\n", block_id(block));
/* computerator (ir3 assembler) doesn't really use blocks for flow
* control, so block->predecessors will be null.
*/
if (block->predecessors && block->predecessors->entries > 0) {
unsigned i = 0;
if (block->predecessors_count > 0) {
tab(lvl+1);
printf("pred: ");
set_foreach (block->predecessors, entry) {
struct ir3_block *pred = (struct ir3_block *)entry->key;
if (i++)
for (unsigned i = 0; i < block->predecessors_count; i++) {
struct ir3_block *pred = block->predecessors[i];
if (i != 0)
printf(", ");
printf("block%u", block_id(pred));
}