mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 05:08:08 +02:00
i965: Add support for gen6 BREAK ISA emit.
There are now two targets: the hop-to-end-of-block target, and the target for where to resume execution for active channels.
This commit is contained in:
parent
4890e0f09c
commit
00e5a743e2
4 changed files with 112 additions and 10 deletions
|
|
@ -1009,6 +1009,7 @@ void brw_math_invert( struct brw_compile *p,
|
|||
void brw_set_src1( struct brw_instruction *insn,
|
||||
struct brw_reg reg );
|
||||
|
||||
void brw_set_uip_jip(struct brw_compile *p);
|
||||
|
||||
/* brw_optimize.c */
|
||||
void brw_optimize(struct brw_compile *p);
|
||||
|
|
|
|||
|
|
@ -1029,16 +1029,24 @@ void brw_ENDIF(struct brw_compile *p,
|
|||
|
||||
struct brw_instruction *brw_BREAK(struct brw_compile *p, int pop_count)
|
||||
{
|
||||
struct intel_context *intel = &p->brw->intel;
|
||||
struct brw_instruction *insn;
|
||||
|
||||
insn = next_insn(p, BRW_OPCODE_BREAK);
|
||||
brw_set_dest(insn, brw_ip_reg());
|
||||
brw_set_src0(insn, brw_ip_reg());
|
||||
brw_set_src1(insn, brw_imm_d(0x0));
|
||||
if (intel->gen >= 6) {
|
||||
brw_set_dest(insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
|
||||
brw_set_src0(insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
|
||||
brw_set_src1(insn, brw_imm_d(0x0));
|
||||
} else {
|
||||
brw_set_dest(insn, brw_ip_reg());
|
||||
brw_set_src0(insn, brw_ip_reg());
|
||||
brw_set_src1(insn, brw_imm_d(0x0));
|
||||
insn->bits3.if_else.pad0 = 0;
|
||||
insn->bits3.if_else.pop_count = pop_count;
|
||||
}
|
||||
insn->header.compression_control = BRW_COMPRESSION_NONE;
|
||||
insn->header.execution_size = BRW_EXECUTE_8;
|
||||
/* insn->header.mask_control = BRW_MASK_DISABLE; */
|
||||
insn->bits3.if_else.pad0 = 0;
|
||||
insn->bits3.if_else.pop_count = pop_count;
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
|
|
@ -2013,6 +2021,78 @@ void brw_urb_WRITE(struct brw_compile *p,
|
|||
swizzle);
|
||||
}
|
||||
|
||||
static int
|
||||
brw_find_next_block_end(struct brw_compile *p, int start)
|
||||
{
|
||||
int ip;
|
||||
|
||||
for (ip = start + 1; ip < p->nr_insn; ip++) {
|
||||
struct brw_instruction *insn = &p->store[ip];
|
||||
|
||||
switch (insn->header.opcode) {
|
||||
case BRW_OPCODE_ENDIF:
|
||||
case BRW_OPCODE_ELSE:
|
||||
case BRW_OPCODE_WHILE:
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
assert(!"not reached");
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
/* There is no DO instruction on gen6, so to find the end of the loop
|
||||
* we have to see if the loop is jumping back before our start
|
||||
* instruction.
|
||||
*/
|
||||
static int
|
||||
brw_find_loop_end(struct brw_compile *p, int start)
|
||||
{
|
||||
int ip;
|
||||
int br = 2;
|
||||
|
||||
for (ip = start + 1; ip < p->nr_insn; ip++) {
|
||||
struct brw_instruction *insn = &p->store[ip];
|
||||
|
||||
if (insn->header.opcode == BRW_OPCODE_WHILE) {
|
||||
if (ip + insn->bits1.branch_gen6.jump_count / br < start)
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
assert(!"not reached");
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
/* After program generation, go back and update the UIP and JIP of
|
||||
* BREAK and CONT instructions to their correct locations.
|
||||
*/
|
||||
void
|
||||
brw_set_uip_jip(struct brw_compile *p)
|
||||
{
|
||||
struct intel_context *intel = &p->brw->intel;
|
||||
int ip;
|
||||
int br = 2;
|
||||
|
||||
if (intel->gen < 6)
|
||||
return;
|
||||
|
||||
for (ip = 0; ip < p->nr_insn; ip++) {
|
||||
struct brw_instruction *insn = &p->store[ip];
|
||||
|
||||
switch (insn->header.opcode) {
|
||||
case BRW_OPCODE_BREAK:
|
||||
insn->bits3.break_cont.jip = br * (brw_find_next_block_end(p, ip) - ip);
|
||||
insn->bits3.break_cont.uip = br * (brw_find_loop_end(p, ip) - ip + 1);
|
||||
break;
|
||||
case BRW_OPCODE_CONTINUE:
|
||||
/* JIP is set at CONTINUE emit time, since that's when we
|
||||
* know where the start of the loop is.
|
||||
*/
|
||||
insn->bits3.break_cont.uip = br * (brw_find_next_block_end(p, ip) - ip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void brw_ff_sync(struct brw_compile *p,
|
||||
struct brw_reg dest,
|
||||
GLuint msg_reg_nr,
|
||||
|
|
|
|||
|
|
@ -933,6 +933,10 @@ fs_visitor::visit(ir_expression *ir)
|
|||
assert(!"not reached: should be handled by lower_noise");
|
||||
break;
|
||||
|
||||
case ir_quadop_vector:
|
||||
assert(!"not reached: should be handled by lower_quadop_vector");
|
||||
break;
|
||||
|
||||
case ir_unop_sqrt:
|
||||
emit_math(FS_OPCODE_SQRT, this->result, op[0]);
|
||||
break;
|
||||
|
|
@ -3375,10 +3379,6 @@ fs_visitor::generate_code()
|
|||
break;
|
||||
|
||||
case BRW_OPCODE_DO:
|
||||
/* FINISHME: We need to write the loop instruction support still. */
|
||||
if (intel->gen >= 6)
|
||||
this->fail = true;
|
||||
|
||||
loop_stack[loop_stack_depth++] = brw_DO(p, BRW_EXECUTE_8);
|
||||
if_depth_in_loop[loop_stack_depth] = 0;
|
||||
break;
|
||||
|
|
@ -3388,6 +3388,10 @@ fs_visitor::generate_code()
|
|||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
break;
|
||||
case BRW_OPCODE_CONTINUE:
|
||||
/* FINISHME: We need to write the loop instruction support still. */
|
||||
if (intel->gen >= 6)
|
||||
this->fail = true;
|
||||
|
||||
brw_CONT(p, if_depth_in_loop[loop_stack_depth]);
|
||||
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
|
||||
break;
|
||||
|
|
@ -3491,6 +3495,8 @@ fs_visitor::generate_code()
|
|||
last_native_inst = p->nr_insn;
|
||||
}
|
||||
|
||||
brw_set_uip_jip(p);
|
||||
|
||||
/* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS
|
||||
* emit issues, it doesn't get the jump distances into the output,
|
||||
* which is often something we want to debug. So this is here in
|
||||
|
|
|
|||
|
|
@ -1539,6 +1539,21 @@ struct brw_instruction
|
|||
GLuint pad0:12;
|
||||
} if_else;
|
||||
|
||||
struct
|
||||
{
|
||||
/* Signed jump distance to the ip to jump to if all channels
|
||||
* are disabled after the break or continue. It should point
|
||||
* to the end of the innermost control flow block, as that's
|
||||
* where some channel could get re-enabled.
|
||||
*/
|
||||
int jip:16;
|
||||
|
||||
/* Signed jump distance to the location to resume execution
|
||||
* of this channel if it's enabled for the break or continue.
|
||||
*/
|
||||
int uip:16;
|
||||
} break_cont;
|
||||
|
||||
struct {
|
||||
GLuint function:4;
|
||||
GLuint int_type:1;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue