i965: Make instruction lists local to the bblocks.
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
This commit is contained in:
parent
3fe1a84bbe
commit
49374fab5d
|
@ -54,9 +54,7 @@ bblock_t::bblock_t(cfg_t *cfg) :
|
|||
cfg(cfg), start_ip(0), end_ip(0), num(0),
|
||||
if_block(NULL), else_block(NULL)
|
||||
{
|
||||
start = NULL;
|
||||
end = NULL;
|
||||
|
||||
instructions.make_empty();
|
||||
parents.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)
|
||||
return false;
|
||||
|
||||
if (ends_block(this->end) ||
|
||||
starts_block(that->start))
|
||||
if (ends_block(this->end()) ||
|
||||
starts_block(that->start()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -138,8 +136,8 @@ bblock_t::combine_with(bblock_t *that)
|
|||
}
|
||||
|
||||
this->end_ip = that->end_ip;
|
||||
this->end = that->end;
|
||||
this->else_block = that->else_block;
|
||||
this->instructions.append_list(&that->instructions);
|
||||
|
||||
this->cfg->remove_block(that);
|
||||
}
|
||||
|
@ -148,9 +146,7 @@ void
|
|||
bblock_t::dump(backend_visitor *v) const
|
||||
{
|
||||
int ip = this->start_ip;
|
||||
for (backend_instruction *inst = (backend_instruction *)this->start;
|
||||
inst != this->end->next;
|
||||
inst = (backend_instruction *) inst->next) {
|
||||
foreach_inst_in_block(backend_instruction, inst, this) {
|
||||
fprintf(stderr, "%5d: ", ip);
|
||||
v->dump_instruction(inst);
|
||||
ip++;
|
||||
|
@ -178,16 +174,15 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
|
||||
set_next_block(&cur, entry, ip);
|
||||
|
||||
entry->start = (backend_instruction *) instructions->get_head();
|
||||
|
||||
foreach_in_list(backend_instruction, inst, instructions) {
|
||||
cur->end = inst;
|
||||
|
||||
foreach_in_list_safe(backend_instruction, inst, instructions) {
|
||||
/* set_next_block wants the post-incremented ip */
|
||||
ip++;
|
||||
|
||||
switch (inst->opcode) {
|
||||
case BRW_OPCODE_IF:
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
|
||||
/* Push our information onto a stack so we can recover from
|
||||
* nested ifs.
|
||||
*/
|
||||
|
@ -202,44 +197,46 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
* instructions.
|
||||
*/
|
||||
next = new_block();
|
||||
next->start = (backend_instruction *)inst->next;
|
||||
cur_if->add_successor(mem_ctx, next);
|
||||
|
||||
set_next_block(&cur, next, ip);
|
||||
break;
|
||||
|
||||
case BRW_OPCODE_ELSE:
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
|
||||
cur_else = cur;
|
||||
|
||||
next = new_block();
|
||||
next->start = (backend_instruction *)inst->next;
|
||||
cur_if->add_successor(mem_ctx, next);
|
||||
|
||||
set_next_block(&cur, next, ip);
|
||||
break;
|
||||
|
||||
case BRW_OPCODE_ENDIF: {
|
||||
if (cur->start == inst) {
|
||||
if (cur->instructions.is_empty()) {
|
||||
/* New block was just created; use it. */
|
||||
cur_endif = cur;
|
||||
} else {
|
||||
cur_endif = new_block();
|
||||
cur_endif->start = inst;
|
||||
|
||||
cur->end = (backend_instruction *)inst->prev;
|
||||
cur->add_successor(mem_ctx, cur_endif);
|
||||
|
||||
set_next_block(&cur, cur_endif, ip - 1);
|
||||
}
|
||||
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
|
||||
if (cur_else) {
|
||||
cur_else->add_successor(mem_ctx, cur_endif);
|
||||
} else {
|
||||
cur_if->add_successor(mem_ctx, cur_endif);
|
||||
}
|
||||
|
||||
assert(cur_if->end->opcode == BRW_OPCODE_IF);
|
||||
assert(!cur_else || cur_else->end->opcode == BRW_OPCODE_ELSE);
|
||||
assert(cur_if->end()->opcode == BRW_OPCODE_IF);
|
||||
assert(!cur_else || cur_else->end()->opcode == BRW_OPCODE_ELSE);
|
||||
|
||||
cur_if->if_block = cur_if;
|
||||
cur_if->else_block = cur_else;
|
||||
|
@ -269,25 +266,28 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
*/
|
||||
cur_while = new_block();
|
||||
|
||||
if (cur->start == inst) {
|
||||
if (cur->instructions.is_empty()) {
|
||||
/* New block was just created; use it. */
|
||||
cur_do = cur;
|
||||
} else {
|
||||
cur_do = new_block();
|
||||
cur_do->start = inst;
|
||||
|
||||
cur->end = (backend_instruction *)inst->prev;
|
||||
cur->add_successor(mem_ctx, cur_do);
|
||||
|
||||
set_next_block(&cur, cur_do, ip - 1);
|
||||
}
|
||||
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
break;
|
||||
|
||||
case BRW_OPCODE_CONTINUE:
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
|
||||
cur->add_successor(mem_ctx, cur_do);
|
||||
|
||||
next = new_block();
|
||||
next->start = (backend_instruction *)inst->next;
|
||||
if (inst->predicate)
|
||||
cur->add_successor(mem_ctx, next);
|
||||
|
||||
|
@ -295,10 +295,12 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
break;
|
||||
|
||||
case BRW_OPCODE_BREAK:
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
|
||||
cur->add_successor(mem_ctx, cur_while);
|
||||
|
||||
next = new_block();
|
||||
next->start = (backend_instruction *)inst->next;
|
||||
if (inst->predicate)
|
||||
cur->add_successor(mem_ctx, next);
|
||||
|
||||
|
@ -306,7 +308,8 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
break;
|
||||
|
||||
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);
|
||||
set_next_block(&cur, cur_while, ip);
|
||||
|
@ -317,12 +320,12 @@ cfg_t::cfg_t(exec_list *instructions)
|
|||
break;
|
||||
|
||||
default:
|
||||
inst->remove();
|
||||
cur->instructions.push_tail(inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(cur->end);
|
||||
|
||||
cur->end_ip = ip;
|
||||
|
||||
make_block_array();
|
||||
|
@ -397,7 +400,6 @@ void
|
|||
cfg_t::set_next_block(bblock_t **cur, bblock_t *block, int ip)
|
||||
{
|
||||
if (*cur) {
|
||||
assert((*cur)->end->next == block->start);
|
||||
(*cur)->end_ip = ip - 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,7 @@ struct bblock_link {
|
|||
struct bblock_t *block;
|
||||
};
|
||||
|
||||
#ifndef __cplusplus
|
||||
struct backend_instruction;
|
||||
#endif
|
||||
|
||||
struct bblock_t {
|
||||
#ifdef __cplusplus
|
||||
|
@ -63,17 +61,20 @@ struct bblock_t {
|
|||
bool can_combine_with(const bblock_t *that) const;
|
||||
void combine_with(bblock_t *that);
|
||||
void dump(backend_visitor *v) const;
|
||||
|
||||
backend_instruction *start();
|
||||
const backend_instruction *start() const;
|
||||
backend_instruction *end();
|
||||
const backend_instruction *end() const;
|
||||
#endif
|
||||
|
||||
struct exec_node link;
|
||||
struct cfg_t *cfg;
|
||||
|
||||
struct backend_instruction *start;
|
||||
struct backend_instruction *end;
|
||||
|
||||
int start_ip;
|
||||
int end_ip;
|
||||
|
||||
struct exec_list instructions;
|
||||
struct exec_list parents;
|
||||
struct exec_list children;
|
||||
int num;
|
||||
|
@ -87,6 +88,56 @@ struct bblock_t {
|
|||
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 {
|
||||
#ifdef __cplusplus
|
||||
DECLARE_RALLOC_CXX_OPERATORS(cfg_t)
|
||||
|
@ -131,31 +182,27 @@ struct cfg_t {
|
|||
foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list)
|
||||
|
||||
#define foreach_inst_in_block(__type, __inst, __block) \
|
||||
for (__type *__inst = (__type *)__block->start; \
|
||||
__inst != __block->end->next; \
|
||||
__inst = (__type *)__inst->next)
|
||||
foreach_in_list(__type, __inst, &(__block)->instructions)
|
||||
|
||||
#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, \
|
||||
*__end = (__type *)__block->end->next->next; \
|
||||
*__end = (__type *)__block->instructions.tail; \
|
||||
__next != __end; \
|
||||
__inst = __next, \
|
||||
__next = (__type *)__next->next)
|
||||
|
||||
#define foreach_inst_in_block_reverse(__type, __inst, __block) \
|
||||
for (__type *__inst = (__type *)__block->end; \
|
||||
__inst != __block->start->prev; \
|
||||
__inst = (__type *)__inst->prev)
|
||||
foreach_in_list_reverse(__type, __inst, &(__block)->instructions)
|
||||
|
||||
#define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst, __block) \
|
||||
for (__type *__scan_inst = (__type *)__inst->next; \
|
||||
__scan_inst != __block->end->next; \
|
||||
!__scan_inst->is_tail_sentinel(); \
|
||||
__scan_inst = (__type *)__scan_inst->next)
|
||||
|
||||
#define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst, __block) \
|
||||
for (__type *__scan_inst = (__type *)__inst->prev; \
|
||||
__scan_inst != __block->start->prev; \
|
||||
!__scan_inst->is_head_sentinel(); \
|
||||
__scan_inst = (__type *)__scan_inst->prev)
|
||||
|
||||
#endif /* BRW_CFG_H */
|
||||
|
|
|
@ -47,19 +47,19 @@ dead_control_flow_eliminate(backend_visitor *v)
|
|||
/* ENDIF instructions, by definition, can only be found at the start of
|
||||
* basic blocks.
|
||||
*/
|
||||
backend_instruction *endif_inst = endif_block->start;
|
||||
backend_instruction *endif_inst = endif_block->start();
|
||||
if (endif_inst->opcode != BRW_OPCODE_ENDIF)
|
||||
continue;
|
||||
|
||||
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) {
|
||||
else_inst = prev_inst;
|
||||
else_block = (bblock_t *)endif_block->link.prev;
|
||||
found = true;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -2258,7 +2258,7 @@ fs_visitor::compute_to_mrf()
|
|||
* values that end up in MRFs are shortly before the MRF
|
||||
* write anyway.
|
||||
*/
|
||||
if (block->start == scan_inst)
|
||||
if (block->start() == scan_inst)
|
||||
break;
|
||||
|
||||
/* 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
|
||||
* 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++) {
|
||||
if (needs_dep[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) {
|
||||
/* 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++) {
|
||||
if (needs_dep[i])
|
||||
scan_inst->insert_before(block,
|
||||
|
|
|
@ -254,12 +254,6 @@ fs_visitor::opt_cse_local(bblock_t *block)
|
|||
fs_inst *prev = (fs_inst *)inst->prev;
|
||||
|
||||
inst->remove(block);
|
||||
|
||||
/* Appending an instruction may have changed our bblock end. */
|
||||
if (inst == block->end) {
|
||||
block->end = prev;
|
||||
}
|
||||
|
||||
inst = prev;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,16 +52,16 @@ fs_visitor::opt_peephole_predicated_break()
|
|||
/* BREAK and CONTINUE instructions, by definition, can only be found at
|
||||
* 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 &&
|
||||
jump_inst->opcode != BRW_OPCODE_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)
|
||||
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)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ brw_fs_alloc_reg_sets(struct intel_screen *screen)
|
|||
static int
|
||||
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;
|
||||
|
||||
int depth = 1;
|
||||
|
@ -203,9 +203,9 @@ count_to_loop_end(const bblock_t *block)
|
|||
for (block = (bblock_t *)block->link.next;
|
||||
depth > 0;
|
||||
block = (bblock_t *)block->link.next) {
|
||||
if (block->start->opcode == BRW_OPCODE_DO)
|
||||
if (block->start()->opcode == BRW_OPCODE_DO)
|
||||
depth++;
|
||||
if (block->end->opcode == BRW_OPCODE_WHILE) {
|
||||
if (block->end()->opcode == BRW_OPCODE_WHILE) {
|
||||
depth--;
|
||||
if (depth == 0)
|
||||
return block->end_ip;
|
||||
|
|
|
@ -128,14 +128,14 @@ fs_visitor::opt_peephole_sel()
|
|||
/* IF instructions, by definition, can only be found at the ends of
|
||||
* 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)
|
||||
continue;
|
||||
|
||||
if (!block->else_block)
|
||||
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 *then_mov[MAX_MOVS] = { NULL };
|
||||
|
|
|
@ -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
|
||||
* 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();
|
||||
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) {
|
||||
|
@ -1370,7 +1370,7 @@ void
|
|||
instruction_scheduler::schedule_instructions(bblock_t *block)
|
||||
{
|
||||
struct brw_context *brw = bv->brw;
|
||||
backend_instruction *inst = block->end;
|
||||
backend_instruction *inst = block->end();
|
||||
time = 0;
|
||||
|
||||
/* 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)
|
||||
block->end->remove(block);
|
||||
if (block->end()->opcode == BRW_OPCODE_NOP)
|
||||
block->end()->remove(block);
|
||||
assert(instructions_to_schedule == 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -778,9 +778,6 @@ backend_instruction::insert_after(bblock_t *block, backend_instruction *inst)
|
|||
|
||||
adjust_later_block_ips(block, 1);
|
||||
|
||||
if (block->end == this)
|
||||
block->end = 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);
|
||||
|
||||
if (block->start == this)
|
||||
block->start = 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);
|
||||
|
||||
if (block->start == this)
|
||||
block->start = (backend_instruction *)list->get_head();
|
||||
|
||||
exec_node::insert_before(list);
|
||||
}
|
||||
|
||||
|
@ -827,11 +818,6 @@ backend_instruction::remove(bblock_t *block)
|
|||
block->cfg->remove_block(block);
|
||||
} else {
|
||||
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();
|
||||
|
|
|
@ -184,12 +184,6 @@ vec4_visitor::opt_cse_local(bblock_t *block)
|
|||
vec4_instruction *prev = (vec4_instruction *)inst->prev;
|
||||
|
||||
inst->remove(block);
|
||||
|
||||
/* Appending an instruction may have changed our bblock end. */
|
||||
if (inst == block->end) {
|
||||
block->end = prev;
|
||||
}
|
||||
|
||||
inst = prev;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ void annotate(struct brw_context *brw,
|
|||
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];
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ void annotate(struct brw_context *brw,
|
|||
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];
|
||||
annotation->cur_block++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue