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:
Eric Anholt 2010-12-01 11:46:46 -08:00
parent 4890e0f09c
commit 00e5a743e2
4 changed files with 112 additions and 10 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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;