return true;
case nir_intrinsic_store_output: {
- alu_node = ppir_node_create_dest(block, ppir_op_store_color, NULL, 0);
+ /* In simple cases where the store_output is ssa, that register
+ * can be directly marked as the output.
+ * If discard is used or the source is not ssa, things can get a
+ * lot more complicated, so don't try to optimize those and fall
+ * back to inserting a mov at the end.
+ * If the source node will only be able to output to pipeline
+ * registers, fall back to the mov as well. */
+ if (!block->comp->uses_discard && instr->src->is_ssa) {
+ node = block->comp->var_nodes[instr->src->ssa->index];
+ switch (node->op) {
+ case ppir_op_load_uniform:
+ case ppir_op_const:
+ break;
+ default:
+ node->is_end = 1;
+ return true;
+ }
+ }
+
+ alu_node = ppir_node_create_dest(block, ppir_op_mov, NULL, 0);
if (!alu_node)
return false;
ppir_node_add_src(block->comp, &alu_node->node, alu_node->src, instr->src,
u_bit_consecutive(0, instr->num_components));
+ alu_node->node.is_end = 1;
+
list_addtail(&alu_node->node.list, &block->node_list);
return true;
}
static void ppir_add_ordering_deps(ppir_compiler *comp)
{
/* Some intrinsics do not have explicit dependencies and thus depend
- * on instructions order. Consider discard_if and store_ouput as
- * example. If we don't add fake dependency of discard_if to store_output
- * scheduler may put store_output first and since store_output terminates
+ * on instructions order. Consider discard_if and the is_end node as
+ * example. If we don't add fake dependency of discard_if to is_end,
+ * scheduler may put the is_end first and since is_end terminates
* shader on Utgard PP, rest of it will never be executed.
* Add fake dependencies for discard/branch/store to preserve
* instruction order.
if (prev_node && ppir_node_is_root(node) && node->op != ppir_op_const) {
ppir_node_add_dep(prev_node, node, ppir_dep_sequence);
}
- if (node->op == ppir_op_discard ||
- node->op == ppir_op_store_color ||
+ if (node->is_end ||
+ node->op == ppir_op_discard ||
node->op == ppir_op_store_temp ||
node->op == ppir_op_branch) {
prev_node = node;
return false;
comp->ra = ra;
+ comp->uses_discard = nir->info.fs.uses_discard;
/* 1st pass: create ppir blocks */
nir_foreach_function(function, nir) {
.name = "const",
.type = ppir_node_type_const,
},
- [ppir_op_store_color] = {
- .name = "st_col",
- .type = ppir_node_type_alu,
- .slots = (int []) {
- PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_ALU_VEC_MUL,
- PPIR_INSTR_SLOT_END
- },
- },
[ppir_op_store_temp] = {
.name = "st_temp",
.type = ppir_node_type_store,
ppir_node_add_dep(move, node, ppir_dep_src);
list_addtail(&move->list, &node->list);
+ if (node->is_end) {
+ node->is_end = false;
+ move->is_end = true;
+ }
+
return move;
}
return ppir_instr_insert_node(succ->instr, node);
}
-static bool ppir_do_one_node_to_instr(ppir_block *block, ppir_node *node, ppir_node **next)
+static bool ppir_do_one_node_to_instr(ppir_block *block, ppir_node *node)
{
switch (node->type) {
case ppir_node_type_alu:
if (!node->instr && !create_new_instr(block, node))
return false;
- if (node->op == ppir_op_store_color)
- node->instr->is_end = true;
-
break;
}
case ppir_node_type_load:
static bool ppir_do_node_to_instr(ppir_block *block, ppir_node *node)
{
- ppir_node *next = node;
-
/* first try pipeline sched, if that didn't succeed try normal scheduling */
if (!ppir_do_node_to_instr_try_insert(block, node))
- if (!ppir_do_one_node_to_instr(block, node, &next))
+ if (!ppir_do_one_node_to_instr(block, node))
return false;
- /* next may have been updated in ppir_do_one_node_to_instr */
- node = next;
+ if (node->is_end)
+ node->instr->is_end = true;
/* we have to make sure the dep not be destroyed (due to
* succ change) in ppir_do_node_to_instr, otherwise we can't