[Mesa-dev] [PATCH] i965: Fix JIP to properly skip over unrelated control flow.
Matt Turner
mattst88 at gmail.com
Thu Nov 19 15:06:56 PST 2015
On Thu, Nov 19, 2015 at 2:05 PM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> We've apparently always been botching JIP for sequences such as:
Wrong since Dec 1 2015! Nice find.
>
> do
> cmp.f0.0 ...
> (+f0.0) break
> ...
> if
> ...
> else
> ...
> endif
> ...
> while
>
> Normally, UIP is supposed to point to the final destination of the jump,
> while in nested control flow, JIP is supposed to point to the end of the
> current nesting level. It essentially bounces out of the current nested
> control flow, to an instruction that has a JIP which bounces out another
> level, and so on.
>
> In the above example, when setting JIP for the BREAK, we call
> brw_find_next_block_end(), which begins a search after the BREAK for the
> next ENDIF, ELSE, WHILE, or HALT. It ignores the IF and finds the ELSE,
> setting JIP there.
>
> This makes no sense at all. The break is supposed to skip over the
> whole if/else/endif block entirely. They have a sibling relationship,
> not a nesting relationship.
>
> This patch fixes brw_find_next_block_end() to track depth as it does
> its search, and ignore anything not at depth 0. So when it sees the
> IF, it ignores everything until after the ENDIF. That way, it finds
> the end of the right block.
>
> Caught while debugging a tessellation shader - no apparent effect on
> Piglit. I did look for actual applications that were affected, and
> found that GLBenchmark Manhattan had a BREAK with a bogus JIP.
>
> Cc: mesa-stable at lists.freedesktop.org
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
> src/mesa/drivers/dri/i965/brw_eu_emit.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
> index da1ddfd..e457fd2 100644
> --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
> +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
> @@ -2604,17 +2604,27 @@ brw_find_next_block_end(struct brw_codegen *p, int start_offset)
> void *store = p->store;
> const struct brw_device_info *devinfo = p->devinfo;
>
> + int depth = 0;
> +
> for (offset = next_offset(devinfo, store, start_offset);
> offset < p->next_insn_offset;
> offset = next_offset(devinfo, store, offset)) {
> brw_inst *insn = store + offset;
>
> switch (brw_inst_opcode(devinfo, insn)) {
> + case BRW_OPCODE_IF:
> + depth++;
> + break;
> case BRW_OPCODE_ENDIF:
> + if (depth == 0)
> + return offset;
> + depth--;
> + break;
> case BRW_OPCODE_ELSE:
> case BRW_OPCODE_WHILE:
> case BRW_OPCODE_HALT:
> - return offset;
> + if (depth == 0)
> + return offset;
Reviewed-by: Matt Turner <mattst88 at gmail.com>
More information about the mesa-dev
mailing list