i965: Make instruction lists local to the bblocks.

Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
This commit is contained in:
Matt Turner 2014-09-01 15:01:23 -07:00
parent 3fe1a84bbe
commit 49374fab5d
12 changed files with 115 additions and 92 deletions

View File

@ -54,9 +54,7 @@ bblock_t::bblock_t(cfg_t *cfg) :
cfg(cfg), start_ip(0), end_ip(0), num(0), cfg(cfg), start_ip(0), end_ip(0), num(0),
if_block(NULL), else_block(NULL) if_block(NULL), else_block(NULL)
{ {
start = NULL; instructions.make_empty();
end = NULL;
parents.make_empty(); parents.make_empty();
children.make_empty(); children.make_empty();
} }
@ -119,8 +117,8 @@ bblock_t::can_combine_with(const bblock_t *that) const
if ((const bblock_t *)this->link.next != that) if ((const bblock_t *)this->link.next != that)
return false; return false;
if (ends_block(this->end) || if (ends_block(this->end()) ||
starts_block(that->start)) starts_block(that->start()))
return false; return false;
return true; return true;
@ -138,8 +136,8 @@ bblock_t::combine_with(bblock_t *that)
} }
this->end_ip = that->end_ip; this->end_ip = that->end_ip;
this->end = that->end;
this->else_block = that->else_block; this->else_block = that->else_block;
this->instructions.append_list(&that->instructions);
this->cfg->remove_block(that); this->cfg->remove_block(that);
} }
@ -148,9 +146,7 @@ void
bblock_t::dump(backend_visitor *v) const bblock_t::dump(backend_visitor *v) const
{ {
int ip = this->start_ip; int ip = this->start_ip;
for (backend_instruction *inst = (backend_instruction *)this->start; foreach_inst_in_block(backend_instruction, inst, this) {
inst != this->end->next;
inst = (backend_instruction *) inst->next) {
fprintf(stderr, "%5d: ", ip); fprintf(stderr, "%5d: ", ip);
v->dump_instruction(inst); v->dump_instruction(inst);
ip++; ip++;
@ -178,16 +174,15 @@ cfg_t::cfg_t(exec_list *instructions)
set_next_block(&cur, entry, ip); set_next_block(&cur, entry, ip);
entry->start = (backend_instruction *) instructions->get_head(); foreach_in_list_safe(backend_instruction, inst, instructions) {
foreach_in_list(backend_instruction, inst, instructions) {
cur->end = inst;
/* set_next_block wants the post-incremented ip */ /* set_next_block wants the post-incremented ip */
ip++; ip++;
switch (inst->opcode) { switch (inst->opcode) {
case BRW_OPCODE_IF: case BRW_OPCODE_IF:
inst->remove();
cur->instructions.push_tail(inst);
/* Push our information onto a stack so we can recover from /* Push our information onto a stack so we can recover from
* nested ifs. * nested ifs.
*/ */
@ -202,44 +197,46 @@ cfg_t::cfg_t(exec_list *instructions)
* instructions. * instructions.
*/ */
next = new_block(); next = new_block();
next->start = (backend_instruction *)inst->next;
cur_if->add_successor(mem_ctx, next); cur_if->add_successor(mem_ctx, next);
set_next_block(&cur, next, ip); set_next_block(&cur, next, ip);
break; break;
case BRW_OPCODE_ELSE: case BRW_OPCODE_ELSE:
inst->remove();
cur->instructions.push_tail(inst);
cur_else = cur; cur_else = cur;
next = new_block(); next = new_block();
next->start = (backend_instruction *)inst->next;
cur_if->add_successor(mem_ctx, next); cur_if->add_successor(mem_ctx, next);
set_next_block(&cur, next, ip); set_next_block(&cur, next, ip);
break; break;
case BRW_OPCODE_ENDIF: { case BRW_OPCODE_ENDIF: {
if (cur->start == inst) { if (cur->instructions.is_empty()) {
/* New block was just created; use it. */ /* New block was just created; use it. */
cur_endif = cur; cur_endif = cur;
} else { } else {
cur_endif = new_block(); cur_endif = new_block();
cur_endif->start = inst;
cur->end = (backend_instruction *)inst->prev;
cur->add_successor(mem_ctx, cur_endif); cur->add_successor(mem_ctx, cur_endif);
set_next_block(&cur, cur_endif, ip - 1); set_next_block(&cur, cur_endif, ip - 1);
} }
inst->remove();
cur->instructions.push_tail(inst);
if (cur_else) { if (cur_else) {
cur_else->add_successor(mem_ctx, cur_endif); cur_else->add_successor(mem_ctx, cur_endif);
} else { } else {
cur_if->add_successor(mem_ctx, cur_endif); cur_if->add_successor(mem_ctx, cur_endif);
} }
assert(cur_if->end->opcode == BRW_OPCODE_IF); assert(cur_if->end()->opcode == BRW_OPCODE_IF);
assert(!cur_else || cur_else->end->opcode == BRW_OPCODE_ELSE); assert(!cur_else || cur_else->end()->opcode == BRW_OPCODE_ELSE);
cur_if->if_block = cur_if; cur_if->if_block = cur_if;
cur_if->else_block = cur_else; cur_if->else_block = cur_else;
@ -269,25 +266,28 @@ cfg_t::cfg_t(exec_list *instructions)
*/ */
cur_while = new_block(); cur_while = new_block();
if (cur->start == inst) { if (cur->instructions.is_empty()) {
/* New block was just created; use it. */ /* New block was just created; use it. */
cur_do = cur; cur_do = cur;
} else { } else {
cur_do = new_block(); cur_do = new_block();
cur_do->start = inst;
cur->end = (backend_instruction *)inst->prev;
cur->add_successor(mem_ctx, cur_do); cur->add_successor(mem_ctx, cur_do);
set_next_block(&cur, cur_do, ip - 1); set_next_block(&cur, cur_do, ip - 1);
} }
inst->remove();
cur->instructions.push_tail(inst);
break; break;
case BRW_OPCODE_CONTINUE: case BRW_OPCODE_CONTINUE:
inst->remove();
cur->instructions.push_tail(inst);
cur->add_successor(mem_ctx, cur_do); cur->add_successor(mem_ctx, cur_do);
next = new_block(); next = new_block();
next->start = (backend_instruction *)inst->next;
if (inst->predicate) if (inst->predicate)
cur->add_successor(mem_ctx, next); cur->add_successor(mem_ctx, next);
@ -295,10 +295,12 @@ cfg_t::cfg_t(exec_list *instructions)
break; break;
case BRW_OPCODE_BREAK: case BRW_OPCODE_BREAK:
inst->remove();
cur->instructions.push_tail(inst);
cur->add_successor(mem_ctx, cur_while); cur->add_successor(mem_ctx, cur_while);
next = new_block(); next = new_block();
next->start = (backend_instruction *)inst->next;
if (inst->predicate) if (inst->predicate)
cur->add_successor(mem_ctx, next); cur->add_successor(mem_ctx, next);
@ -306,7 +308,8 @@ cfg_t::cfg_t(exec_list *instructions)
break; break;
case BRW_OPCODE_WHILE: case BRW_OPCODE_WHILE:
cur_while->start = (backend_instruction *)inst->next; inst->remove();
cur->instructions.push_tail(inst);
cur->add_successor(mem_ctx, cur_do); cur->add_successor(mem_ctx, cur_do);
set_next_block(&cur, cur_while, ip); set_next_block(&cur, cur_while, ip);
@ -317,12 +320,12 @@ cfg_t::cfg_t(exec_list *instructions)
break; break;
default: default:
inst->remove();
cur->instructions.push_tail(inst);
break; break;
} }
} }
assert(cur->end);
cur->end_ip = ip; cur->end_ip = ip;
make_block_array(); make_block_array();
@ -397,7 +400,6 @@ void
cfg_t::set_next_block(bblock_t **cur, bblock_t *block, int ip) cfg_t::set_next_block(bblock_t **cur, bblock_t *block, int ip)
{ {
if (*cur) { if (*cur) {
assert((*cur)->end->next == block->start);
(*cur)->end_ip = ip - 1; (*cur)->end_ip = ip - 1;
} }

View File

@ -47,9 +47,7 @@ struct bblock_link {
struct bblock_t *block; struct bblock_t *block;
}; };
#ifndef __cplusplus
struct backend_instruction; struct backend_instruction;
#endif
struct bblock_t { struct bblock_t {
#ifdef __cplusplus #ifdef __cplusplus
@ -63,17 +61,20 @@ struct bblock_t {
bool can_combine_with(const bblock_t *that) const; bool can_combine_with(const bblock_t *that) const;
void combine_with(bblock_t *that); void combine_with(bblock_t *that);
void dump(backend_visitor *v) const; void dump(backend_visitor *v) const;
backend_instruction *start();
const backend_instruction *start() const;
backend_instruction *end();
const backend_instruction *end() const;
#endif #endif
struct exec_node link; struct exec_node link;
struct cfg_t *cfg; struct cfg_t *cfg;
struct backend_instruction *start;
struct backend_instruction *end;
int start_ip; int start_ip;
int end_ip; int end_ip;
struct exec_list instructions;
struct exec_list parents; struct exec_list parents;
struct exec_list children; struct exec_list children;
int num; int num;
@ -87,6 +88,56 @@ struct bblock_t {
struct bblock_t *else_block; struct bblock_t *else_block;
}; };
static inline struct backend_instruction *
bblock_start(struct bblock_t *block)
{
return (struct backend_instruction *)exec_list_get_head(&block->instructions);
}
static inline const struct backend_instruction *
bblock_start_const(const struct bblock_t *block)
{
return (const struct backend_instruction *)exec_list_get_head_const(&block->instructions);
}
static inline struct backend_instruction *
bblock_end(struct bblock_t *block)
{
return (struct backend_instruction *)exec_list_get_tail(&block->instructions);
}
static inline const struct backend_instruction *
bblock_end_const(const struct bblock_t *block)
{
return (const struct backend_instruction *)exec_list_get_tail_const(&block->instructions);
}
#ifdef __cplusplus
inline backend_instruction *
bblock_t::start()
{
return bblock_start(this);
}
inline const backend_instruction *
bblock_t::start() const
{
return bblock_start_const(this);
}
inline backend_instruction *
bblock_t::end()
{
return bblock_end(this);
}
inline const backend_instruction *
bblock_t::end() const
{
return bblock_end_const(this);
}
#endif
struct cfg_t { struct cfg_t {
#ifdef __cplusplus #ifdef __cplusplus
DECLARE_RALLOC_CXX_OPERATORS(cfg_t) DECLARE_RALLOC_CXX_OPERATORS(cfg_t)
@ -131,31 +182,27 @@ struct cfg_t {
foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list) foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list)
#define foreach_inst_in_block(__type, __inst, __block) \ #define foreach_inst_in_block(__type, __inst, __block) \
for (__type *__inst = (__type *)__block->start; \ foreach_in_list(__type, __inst, &(__block)->instructions)
__inst != __block->end->next; \
__inst = (__type *)__inst->next)
#define foreach_inst_in_block_safe(__type, __inst, __block) \ #define foreach_inst_in_block_safe(__type, __inst, __block) \
for (__type *__inst = (__type *)__block->start, \ for (__type *__inst = (__type *)__block->instructions.head, \
*__next = (__type *)__inst->next, \ *__next = (__type *)__inst->next, \
*__end = (__type *)__block->end->next->next; \ *__end = (__type *)__block->instructions.tail; \
__next != __end; \ __next != __end; \
__inst = __next, \ __inst = __next, \
__next = (__type *)__next->next) __next = (__type *)__next->next)
#define foreach_inst_in_block_reverse(__type, __inst, __block) \ #define foreach_inst_in_block_reverse(__type, __inst, __block) \
for (__type *__inst = (__type *)__block->end; \ foreach_in_list_reverse(__type, __inst, &(__block)->instructions)
__inst != __block->start->prev; \
__inst = (__type *)__inst->prev)
#define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst, __block) \ #define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst, __block) \
for (__type *__scan_inst = (__type *)__inst->next; \ for (__type *__scan_inst = (__type *)__inst->next; \
__scan_inst != __block->end->next; \ !__scan_inst->is_tail_sentinel(); \
__scan_inst = (__type *)__scan_inst->next) __scan_inst = (__type *)__scan_inst->next)
#define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst, __block) \ #define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst, __block) \
for (__type *__scan_inst = (__type *)__inst->prev; \ for (__type *__scan_inst = (__type *)__inst->prev; \
__scan_inst != __block->start->prev; \ !__scan_inst->is_head_sentinel(); \
__scan_inst = (__type *)__scan_inst->prev) __scan_inst = (__type *)__scan_inst->prev)
#endif /* BRW_CFG_H */ #endif /* BRW_CFG_H */

View File

@ -47,19 +47,19 @@ dead_control_flow_eliminate(backend_visitor *v)
/* ENDIF instructions, by definition, can only be found at the start of /* ENDIF instructions, by definition, can only be found at the start of
* basic blocks. * basic blocks.
*/ */
backend_instruction *endif_inst = endif_block->start; backend_instruction *endif_inst = endif_block->start();
if (endif_inst->opcode != BRW_OPCODE_ENDIF) if (endif_inst->opcode != BRW_OPCODE_ENDIF)
continue; continue;
backend_instruction *if_inst = NULL, *else_inst = NULL; backend_instruction *if_inst = NULL, *else_inst = NULL;
backend_instruction *prev_inst = ((bblock_t *)endif_block->link.prev)->end; backend_instruction *prev_inst = ((bblock_t *)endif_block->link.prev)->end();
if (prev_inst->opcode == BRW_OPCODE_ELSE) { if (prev_inst->opcode == BRW_OPCODE_ELSE) {
else_inst = prev_inst; else_inst = prev_inst;
else_block = (bblock_t *)endif_block->link.prev; else_block = (bblock_t *)endif_block->link.prev;
found = true; found = true;
if (else_block->start_ip == else_block->end_ip) if (else_block->start_ip == else_block->end_ip)
prev_inst = ((bblock_t *)else_block->link.prev)->end; prev_inst = ((bblock_t *)else_block->link.prev)->end();
} }
if (prev_inst->opcode == BRW_OPCODE_IF) { if (prev_inst->opcode == BRW_OPCODE_IF) {

View File

@ -2258,7 +2258,7 @@ fs_visitor::compute_to_mrf()
* values that end up in MRFs are shortly before the MRF * values that end up in MRFs are shortly before the MRF
* write anyway. * write anyway.
*/ */
if (block->start == scan_inst) if (block->start() == scan_inst)
break; break;
/* You can't read from an MRF, so if someone else reads our /* You can't read from an MRF, so if someone else reads our
@ -2562,7 +2562,7 @@ fs_visitor::insert_gen4_pre_send_dependency_workarounds(bblock_t *block,
/* If we hit control flow, assume that there *are* outstanding /* If we hit control flow, assume that there *are* outstanding
* dependencies, and force their cleanup before our instruction. * dependencies, and force their cleanup before our instruction.
*/ */
if (block->start == scan_inst) { if (block->start() == scan_inst) {
for (int i = 0; i < write_len; i++) { for (int i = 0; i < write_len; i++) {
if (needs_dep[i]) { if (needs_dep[i]) {
inst->insert_before(block, DEP_RESOLVE_MOV(first_write_grf + i)); inst->insert_before(block, DEP_RESOLVE_MOV(first_write_grf + i));
@ -2631,7 +2631,7 @@ fs_visitor::insert_gen4_post_send_dependency_workarounds(bblock_t *block, fs_ins
*/ */
foreach_inst_in_block_starting_from(fs_inst, scan_inst, inst, block) { foreach_inst_in_block_starting_from(fs_inst, scan_inst, inst, block) {
/* If we hit control flow, force resolve all remaining dependencies. */ /* If we hit control flow, force resolve all remaining dependencies. */
if (block->end == scan_inst) { if (block->end() == scan_inst) {
for (int i = 0; i < write_len; i++) { for (int i = 0; i < write_len; i++) {
if (needs_dep[i]) if (needs_dep[i])
scan_inst->insert_before(block, scan_inst->insert_before(block,

View File

@ -254,12 +254,6 @@ fs_visitor::opt_cse_local(bblock_t *block)
fs_inst *prev = (fs_inst *)inst->prev; fs_inst *prev = (fs_inst *)inst->prev;
inst->remove(block); inst->remove(block);
/* Appending an instruction may have changed our bblock end. */
if (inst == block->end) {
block->end = prev;
}
inst = prev; inst = prev;
} }
} }

View File

@ -52,16 +52,16 @@ fs_visitor::opt_peephole_predicated_break()
/* BREAK and CONTINUE instructions, by definition, can only be found at /* BREAK and CONTINUE instructions, by definition, can only be found at
* the ends of basic blocks. * the ends of basic blocks.
*/ */
fs_inst *jump_inst = (fs_inst *)block->end; fs_inst *jump_inst = (fs_inst *)block->end();
if (jump_inst->opcode != BRW_OPCODE_BREAK && if (jump_inst->opcode != BRW_OPCODE_BREAK &&
jump_inst->opcode != BRW_OPCODE_CONTINUE) jump_inst->opcode != BRW_OPCODE_CONTINUE)
continue; continue;
fs_inst *if_inst = (fs_inst *)((bblock_t *)block->link.prev)->end; fs_inst *if_inst = (fs_inst *)((bblock_t *)block->link.prev)->end();
if (if_inst->opcode != BRW_OPCODE_IF) if (if_inst->opcode != BRW_OPCODE_IF)
continue; continue;
fs_inst *endif_inst = (fs_inst *)((bblock_t *)block->link.next)->start; fs_inst *endif_inst = (fs_inst *)((bblock_t *)block->link.next)->start();
if (endif_inst->opcode != BRW_OPCODE_ENDIF) if (endif_inst->opcode != BRW_OPCODE_ENDIF)
continue; continue;

View File

@ -193,7 +193,7 @@ brw_fs_alloc_reg_sets(struct intel_screen *screen)
static int static int
count_to_loop_end(const bblock_t *block) count_to_loop_end(const bblock_t *block)
{ {
if (block->end->opcode == BRW_OPCODE_WHILE) if (block->end()->opcode == BRW_OPCODE_WHILE)
return block->end_ip; return block->end_ip;
int depth = 1; int depth = 1;
@ -203,9 +203,9 @@ count_to_loop_end(const bblock_t *block)
for (block = (bblock_t *)block->link.next; for (block = (bblock_t *)block->link.next;
depth > 0; depth > 0;
block = (bblock_t *)block->link.next) { block = (bblock_t *)block->link.next) {
if (block->start->opcode == BRW_OPCODE_DO) if (block->start()->opcode == BRW_OPCODE_DO)
depth++; depth++;
if (block->end->opcode == BRW_OPCODE_WHILE) { if (block->end()->opcode == BRW_OPCODE_WHILE) {
depth--; depth--;
if (depth == 0) if (depth == 0)
return block->end_ip; return block->end_ip;

View File

@ -128,14 +128,14 @@ fs_visitor::opt_peephole_sel()
/* IF instructions, by definition, can only be found at the ends of /* IF instructions, by definition, can only be found at the ends of
* basic blocks. * basic blocks.
*/ */
fs_inst *if_inst = (fs_inst *) block->end; fs_inst *if_inst = (fs_inst *)block->end();
if (if_inst->opcode != BRW_OPCODE_IF) if (if_inst->opcode != BRW_OPCODE_IF)
continue; continue;
if (!block->else_block) if (!block->else_block)
continue; continue;
assert(block->else_block->end->opcode == BRW_OPCODE_ELSE); assert(block->else_block->end()->opcode == BRW_OPCODE_ELSE);
fs_inst *else_mov[MAX_MOVS] = { NULL }; fs_inst *else_mov[MAX_MOVS] = { NULL };
fs_inst *then_mov[MAX_MOVS] = { NULL }; fs_inst *then_mov[MAX_MOVS] = { NULL };

View File

@ -631,10 +631,10 @@ instruction_scheduler::add_insts_from_block(bblock_t *block)
/* Removing the last instruction from a basic block removes the block as /* Removing the last instruction from a basic block removes the block as
* well, so put a NOP at the end to keep it alive. * well, so put a NOP at the end to keep it alive.
*/ */
if (!block->end->is_control_flow()) { if (!block->end()->is_control_flow()) {
backend_instruction *nop = new(mem_ctx) backend_instruction(); backend_instruction *nop = new(mem_ctx) backend_instruction();
nop->opcode = BRW_OPCODE_NOP; nop->opcode = BRW_OPCODE_NOP;
block->end->insert_after(block, nop); block->end()->insert_after(block, nop);
} }
foreach_inst_in_block_safe(backend_instruction, inst, block) { foreach_inst_in_block_safe(backend_instruction, inst, block) {
@ -1370,7 +1370,7 @@ void
instruction_scheduler::schedule_instructions(bblock_t *block) instruction_scheduler::schedule_instructions(bblock_t *block)
{ {
struct brw_context *brw = bv->brw; struct brw_context *brw = bv->brw;
backend_instruction *inst = block->end; backend_instruction *inst = block->end();
time = 0; time = 0;
/* Remove non-DAG heads from the list. */ /* Remove non-DAG heads from the list. */
@ -1448,8 +1448,8 @@ instruction_scheduler::schedule_instructions(bblock_t *block)
} }
} }
if (block->end->opcode == BRW_OPCODE_NOP) if (block->end()->opcode == BRW_OPCODE_NOP)
block->end->remove(block); block->end()->remove(block);
assert(instructions_to_schedule == 0); assert(instructions_to_schedule == 0);
} }

View File

@ -778,9 +778,6 @@ backend_instruction::insert_after(bblock_t *block, backend_instruction *inst)
adjust_later_block_ips(block, 1); adjust_later_block_ips(block, 1);
if (block->end == this)
block->end = inst;
exec_node::insert_after(inst); exec_node::insert_after(inst);
} }
@ -793,9 +790,6 @@ backend_instruction::insert_before(bblock_t *block, backend_instruction *inst)
adjust_later_block_ips(block, 1); adjust_later_block_ips(block, 1);
if (block->start == this)
block->start = inst;
exec_node::insert_before(inst); exec_node::insert_before(inst);
} }
@ -810,9 +804,6 @@ backend_instruction::insert_before(bblock_t *block, exec_list *list)
adjust_later_block_ips(block, num_inst); adjust_later_block_ips(block, num_inst);
if (block->start == this)
block->start = (backend_instruction *)list->get_head();
exec_node::insert_before(list); exec_node::insert_before(list);
} }
@ -827,11 +818,6 @@ backend_instruction::remove(bblock_t *block)
block->cfg->remove_block(block); block->cfg->remove_block(block);
} else { } else {
block->end_ip--; block->end_ip--;
if (block->start == this)
block->start = (backend_instruction *)this->next;
if (block->end == this)
block->end = (backend_instruction *)this->prev;
} }
exec_node::remove(); exec_node::remove();

View File

@ -184,12 +184,6 @@ vec4_visitor::opt_cse_local(bblock_t *block)
vec4_instruction *prev = (vec4_instruction *)inst->prev; vec4_instruction *prev = (vec4_instruction *)inst->prev;
inst->remove(block); inst->remove(block);
/* Appending an instruction may have changed our bblock end. */
if (inst == block->end) {
block->end = prev;
}
inst = prev; inst = prev;
} }
} }

View File

@ -114,7 +114,7 @@ void annotate(struct brw_context *brw,
ann->annotation = inst->annotation; ann->annotation = inst->annotation;
} }
if (cfg->blocks[annotation->cur_block]->start == inst) { if (bblock_start(cfg->blocks[annotation->cur_block]) == inst) {
ann->block_start = cfg->blocks[annotation->cur_block]; ann->block_start = cfg->blocks[annotation->cur_block];
} }
@ -130,7 +130,7 @@ void annotate(struct brw_context *brw,
annotation->ann_count--; annotation->ann_count--;
} }
if (cfg->blocks[annotation->cur_block]->end == inst) { if (bblock_end(cfg->blocks[annotation->cur_block]) == inst) {
ann->block_end = cfg->blocks[annotation->cur_block]; ann->block_end = cfg->blocks[annotation->cur_block];
annotation->cur_block++; annotation->cur_block++;
} }