aco/assembler: Fix short jumps over chained branches

If we insert

   <code>
   s_branch 1
   s_branch Target

at the end of some block, and later hide an additional chained branch
after the existing one, then we have to update the 's_branch 1' to
also jump over the newly added branch.

Fixes: cab5639a09 ('aco/assembler: chain branches instead of emitting long jumps')
Closes: #12673
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33762>
(cherry picked from commit 6659db285a)
This commit is contained in:
Daniel Schürmann 2025-02-26 12:38:58 +01:00 committed by Eric Engestrom
parent 4a08708ca2
commit 553ab18656
2 changed files with 9 additions and 1 deletions

View file

@ -154,7 +154,7 @@
"description": "aco/assembler: Fix short jumps over chained branches",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "cab5639a09ab954e67af27486a0f9b41a0373d98",
"notes": null

View file

@ -1538,6 +1538,8 @@ chain_branches(asm_context& ctx, std::vector<uint32_t>& out, branch_info& branch
unsigned target = branch.target;
branch.target = new_block->index;
unsigned skip_branch_target = 0; /* Target of potentially inserted short jump. */
/* Find suitable insertion point:
* We define two offset ranges within our new branch instruction should be placed.
* Then we try to maximize the distance from either the previous branch or the target.
@ -1604,6 +1606,7 @@ chain_branches(asm_context& ctx, std::vector<uint32_t>& out, branch_info& branch
bld.reset(&ctx.program->blocks[insertion_block_idx].instructions, it);
} else {
bld.reset(&ctx.program->blocks[insertion_block_idx - 1].instructions);
skip_branch_target = insertion_block_idx;
}
/* Since we insert a branch into existing code, mitigate LdsBranchVmemWARHazard on GFX10. */
@ -1623,6 +1626,11 @@ chain_branches(asm_context& ctx, std::vector<uint32_t>& out, branch_info& branch
insert_code(ctx, out, insert_at, code.size(), code.data());
new_block->offset = block_offset;
if (skip_branch_target) {
/* If we insert a short jump over the new branch at the end of a block,
* ensure that it gets updated accordingly after additional changes. */
ctx.branches.push_back({block_offset - 1, skip_branch_target});
}
ctx.branches.push_back({block_offset, target});
assert(out[ctx.branches.back().pos] == code.back());
}