summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2019-06-29 04:52:47 -0700
committerEric Anholt <[email protected]>2019-08-28 15:25:25 -0700
commit6af70aa2b457d2c2dc8c7818f71459f407f99eae (patch)
tree590ef3300414cc2c13197e85c51ad6d4af2da4ae /src
parent06bc4875fff8ad144dbebebe53241da4655aecc6 (diff)
freedreno/ir3: maintain predecessors/successors
While resolving jumps to skip intermediate jumps from the structured CFG, maintain the successors and predecessors correctly. Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/freedreno/ir3/ir3_legalize.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/freedreno/ir3/ir3_legalize.c b/src/freedreno/ir3/ir3_legalize.c
index e46d1214d60..2fb7f9de6f1 100644
--- a/src/freedreno/ir3/ir3_legalize.c
+++ b/src/freedreno/ir3/ir3_legalize.c
@@ -400,6 +400,47 @@ resolve_dest_block(struct ir3_block *block)
return block;
}
+static void
+remove_unused_block(struct ir3_block *old_target)
+{
+ list_delinit(&old_target->node);
+
+ /* cleanup dangling predecessors: */
+ 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);
+ }
+ }
+}
+
+static void
+retarget_jump(struct ir3_instruction *instr, struct ir3_block *new_target)
+{
+ struct ir3_block *old_target = instr->cat0.target;
+ struct ir3_block *cur_block = instr->block;
+
+ /* update current blocks successors to reflect the retargetting: */
+ if (cur_block->successors[0] == old_target) {
+ cur_block->successors[0] = new_target;
+ } else {
+ debug_assert(cur_block->successors[1] == old_target);
+ cur_block->successors[1] = new_target;
+ }
+
+ /* update new target's predecessors: */
+ _mesa_set_add(new_target->predecessors, 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);
+
+ if (old_target->predecessors->entries == 0)
+ remove_unused_block(old_target);
+
+ instr->cat0.target = new_target;
+}
+
static bool
resolve_jump(struct ir3_instruction *instr)
{
@@ -408,8 +449,7 @@ resolve_jump(struct ir3_instruction *instr)
struct ir3_instruction *target;
if (tblock != instr->cat0.target) {
- list_delinit(&instr->cat0.target->node);
- instr->cat0.target = tblock;
+ retarget_jump(instr, tblock);
return true;
}