agx: Add break_if_*cmp instructions
To faciliate break optimizations. We use a more efficient lowering than the literal transition of the NIR. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25052>
This commit is contained in:

committed by
Marge Bot

parent
ff816f224b
commit
ffb64283ee
@@ -8,6 +8,42 @@
|
|||||||
#include "agx_opcodes.h"
|
#include "agx_opcodes.h"
|
||||||
|
|
||||||
/* Lower pseudo instructions created during optimization. */
|
/* Lower pseudo instructions created during optimization. */
|
||||||
|
|
||||||
|
static agx_instr *
|
||||||
|
while_for_break_if(agx_builder *b, agx_instr *I)
|
||||||
|
{
|
||||||
|
if (I->op == AGX_OPCODE_BREAK_IF_FCMP) {
|
||||||
|
return agx_while_fcmp(b, I->src[0], I->src[1], I->nest, I->fcond,
|
||||||
|
!I->invert_cond);
|
||||||
|
} else {
|
||||||
|
return agx_while_icmp(b, I->src[0], I->src[1], I->nest, I->icond,
|
||||||
|
!I->invert_cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static agx_instr *
|
||||||
|
cmpsel_for_break_if(agx_builder *b, agx_instr *I)
|
||||||
|
{
|
||||||
|
agx_index r0l = agx_register(0, AGX_SIZE_16);
|
||||||
|
|
||||||
|
/* If the condition is true, set r0l to nest to break */
|
||||||
|
agx_index t = agx_immediate(I->nest);
|
||||||
|
agx_index f = r0l;
|
||||||
|
|
||||||
|
if (I->invert_cond) {
|
||||||
|
agx_index temp = t;
|
||||||
|
t = f;
|
||||||
|
f = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (I->op == AGX_OPCODE_BREAK_IF_FCMP)
|
||||||
|
agx_fcmpsel_to(b, r0l, I->src[0], I->src[1], t, f, I->fcond);
|
||||||
|
else
|
||||||
|
agx_icmpsel_to(b, r0l, I->src[0], I->src[1], t, f, I->icond);
|
||||||
|
|
||||||
|
return agx_push_exec(b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static agx_instr *
|
static agx_instr *
|
||||||
lower(agx_builder *b, agx_instr *I)
|
lower(agx_builder *b, agx_instr *I)
|
||||||
{
|
{
|
||||||
@@ -37,6 +73,14 @@ lower(agx_builder *b, agx_instr *I)
|
|||||||
agx_mov_imm_to(b, agx_register(0, AGX_SIZE_16), I->nest);
|
agx_mov_imm_to(b, agx_register(0, AGX_SIZE_16), I->nest);
|
||||||
return agx_pop_exec(b, 0);
|
return agx_pop_exec(b, 0);
|
||||||
|
|
||||||
|
case AGX_OPCODE_BREAK_IF_ICMP:
|
||||||
|
case AGX_OPCODE_BREAK_IF_FCMP: {
|
||||||
|
if (I->nest == 1)
|
||||||
|
return while_for_break_if(b, I);
|
||||||
|
else
|
||||||
|
return cmpsel_for_break_if(b, I);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@@ -424,3 +424,8 @@ op("preload", _, srcs = 1, schedule_class = "preload")
|
|||||||
op("begin_cf", _, dests = 0, can_eliminate = False)
|
op("begin_cf", _, dests = 0, can_eliminate = False)
|
||||||
op("break", _, dests = 0, imms = [NEST], can_eliminate = False,
|
op("break", _, dests = 0, imms = [NEST], can_eliminate = False,
|
||||||
schedule_class = "invalid")
|
schedule_class = "invalid")
|
||||||
|
|
||||||
|
for (name, is_float) in [("break_if_icmp", False), ("break_if_fcmp", True)]:
|
||||||
|
op(name, _, dests = 0, srcs = 2,
|
||||||
|
imms = [NEST, INVERT_COND, FCOND if is_float else ICOND],
|
||||||
|
can_eliminate = False, schedule_class = "invalid")
|
||||||
|
Reference in New Issue
Block a user