summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/ir3/ir3.c
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2015-06-09 17:17:06 -0400
committerRob Clark <[email protected]>2015-06-21 07:54:38 -0400
commit457f7c2a2a93b45396ac66e0d4b3896d2db8fdf3 (patch)
tree1286493bc6b7fd01738125b6fc91db78c3dc805f /src/gallium/drivers/freedreno/ir3/ir3.c
parent660d5c1646f5d63f9626b24beabc9cfc318849d4 (diff)
freedreno/ir3: block reshuffling and loops!
This shuffles things around to allow the shader to have multiple basic blocks. We drop the entire CFG structure from nir and just preserve the blocks. At scheduling we know whether to schedule conditional branches or unconditional jumps at the end of the block based on the # of block successors. (Dropping jumps to the following instruction, etc.) One slight complication is that variables (load_var/store_var, ie. arrays) are not in SSA form, so we have to figure out where to put the phi's ourself. For this, we use the predecessor set information from nir_block. (We could perhaps use NIR's dominance frontier information to help with this?) Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/ir3/ir3.c')
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.c60
1 files changed, 50 insertions, 10 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.c b/src/gallium/drivers/freedreno/ir3/ir3.c
index ba5851c6c82..a166b67d7cf 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3.c
@@ -80,6 +80,8 @@ struct ir3 * ir3_create(struct ir3_compiler *compiler,
shader->noutputs = nout;
shader->outputs = ir3_alloc(shader, sizeof(shader->outputs[0]) * nout);
+ list_inithead(&shader->block_list);
+
return shader;
}
@@ -548,7 +550,6 @@ static int (*emit[])(struct ir3_instruction *instr, void *ptr,
void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
uint32_t gpu_id)
{
- struct ir3_block *block = shader->block;
uint32_t *ptr, *dwords;
info->gpu_id = gpu_id;
@@ -558,8 +559,10 @@ void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
info->instrs_count = 0;
info->sizedwords = 0;
- list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
- info->sizedwords += 2;
+ list_for_each_entry (struct ir3_block, block, &shader->block_list, node) {
+ list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
+ info->sizedwords += 2;
+ }
}
/* need a integer number of instruction "groups" (sets of 16
@@ -574,12 +577,14 @@ void * ir3_assemble(struct ir3 *shader, struct ir3_info *info,
ptr = dwords = calloc(4, info->sizedwords);
- list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
- int ret = emit[instr->category](instr, dwords, info);
- if (ret)
- goto fail;
- info->instrs_count += 1 + instr->repeat;
- dwords += 2;
+ list_for_each_entry (struct ir3_block, block, &shader->block_list, node) {
+ list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
+ int ret = emit[instr->category](instr, dwords, info);
+ if (ret)
+ goto fail;
+ info->instrs_count += 1 + instr->repeat;
+ dwords += 2;
+ }
}
return ptr;
@@ -617,7 +622,12 @@ static void insert_instr(struct ir3_block *block,
struct ir3_block * ir3_block_create(struct ir3 *shader)
{
struct ir3_block *block = ir3_alloc(shader, sizeof(*block));
+#ifdef DEBUG
+ static uint32_t serialno = 0;
+ block->serialno = ++serialno;
+#endif
block->shader = shader;
+ list_inithead(&block->node);
list_inithead(&block->instr_list);
return block;
}
@@ -688,10 +698,40 @@ struct ir3_instruction * ir3_instr_clone(struct ir3_instruction *instr)
struct ir3_register * ir3_reg_create(struct ir3_instruction *instr,
int num, int flags)
{
- struct ir3_register *reg = reg_create(instr->block->shader, num, flags);
+ struct ir3 *shader = instr->block->shader;
+ struct ir3_register *reg = reg_create(shader, num, flags);
#ifdef DEBUG
debug_assert(instr->regs_count < instr->regs_max);
#endif
instr->regs[instr->regs_count++] = reg;
return reg;
}
+
+void
+ir3_block_clear_mark(struct ir3_block *block)
+{
+ list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node)
+ instr->flags &= ~IR3_INSTR_MARK;
+}
+
+void
+ir3_clear_mark(struct ir3 *ir)
+{
+ list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
+ ir3_block_clear_mark(block);
+ }
+}
+
+/* note: this will destroy instr->depth, don't do it until after sched! */
+void
+ir3_count_instructions(struct ir3 *ir)
+{
+ unsigned ip = 0;
+ list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
+ list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
+ instr->ip = ip++;
+ }
+ block->start_ip = list_first_entry(&block->instr_list, struct ir3_instruction, node)->ip;
+ block->end_ip = list_last_entry(&block->instr_list, struct ir3_instruction, node)->ip;
+ }
+}