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();
}
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;
}
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);
}
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++;
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.
*/
* 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;
*/
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);
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);
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);
break;
default:
+ inst->remove();
+ cur->instructions.push_tail(inst);
break;
}
}
- assert(cur->end);
-
cur->end_ip = ip;
make_block_array();
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;
}
struct bblock_t *block;
};
-#ifndef __cplusplus
struct backend_instruction;
-#endif
struct bblock_t {
#ifdef __cplusplus
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;
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)
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 */
/* 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) {
* 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
/* 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));
*/
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,
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;
}
}
/* 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;
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;
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;
/* 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 };
/* 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) {
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. */
}
}
- 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);
}
adjust_later_block_ips(block, 1);
- if (block->end == this)
- block->end = inst;
-
exec_node::insert_after(inst);
}
adjust_later_block_ips(block, 1);
- if (block->start == this)
- block->start = inst;
-
exec_node::insert_before(inst);
}
adjust_later_block_ips(block, num_inst);
- if (block->start == this)
- block->start = (backend_instruction *)list->get_head();
-
exec_node::insert_before(list);
}
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();
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;
}
}
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];
}
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++;
}