uint8_t swizzle[4] = {0};
if (ppir_instr_insert_const(&ic, nc, swizzle)) {
+ ppir_node *succ = ppir_node_first_succ(node);
+ ppir_src *src = NULL;
+ for (int s = 0; s < ppir_node_get_src_num(succ); s++) {
+ src = ppir_node_get_src(succ, s);
+ if (src->node == node)
+ break;
+ }
+ assert(src->node == node);
+
instr->constant[i] = ic;
- ppir_instr_update_src_pipeline(
- instr, ppir_pipeline_reg_const0 + i, &c->dest, swizzle);
+ ppir_update_src_pipeline(ppir_pipeline_reg_const0 + i, src,
+ &c->dest, swizzle);
break;
}
}
return true;
}
- ppir_node *move = NULL;
- ppir_dest *dest = ppir_node_get_dest(node);
+ assert(ppir_node_has_single_succ(node));
- /* const (register) can only be used in alu node, create a move
- * node for other types of node */
- ppir_node_foreach_succ_safe(node, dep) {
- ppir_node *succ = dep->succ;
+ ppir_node *succ = ppir_node_first_succ(node);
+ ppir_src *src = ppir_node_get_src_for_pred(succ, node);
+ ppir_dest *dest = ppir_node_get_dest(node);
+ assert(src != NULL);
+
+ switch (succ->type) {
+ case ppir_node_type_alu:
+ case ppir_node_type_branch:
+ /* ALU and branch can consume consts directly */
+ dest->type = src->type = ppir_target_pipeline;
+ /* Reg will be updated in node_to_instr later */
+ dest->pipeline = src->pipeline = ppir_pipeline_reg_const0;
+ return true;
+ default:
+ /* Create a move for everyone else */
+ break;
+ }
- if (succ->type != ppir_node_type_alu) {
- if (!move) {
- move = ppir_node_create(block, ppir_op_mov, -1, 0);
- if (unlikely(!move))
- return false;
+ ppir_node *move = ppir_node_create(block, ppir_op_mov, -1, 0);
+ if (unlikely(!move))
+ return false;
- ppir_debug("lower const create move %d for %d\n",
- move->index, node->index);
+ ppir_debug("lower const create move %d for %d\n",
+ move->index, node->index);
- ppir_alu_node *alu = ppir_node_to_alu(move);
- alu->dest = *dest;
- alu->num_src = 1;
- ppir_node_target_assign(alu->src, node);
- for (int i = 0; i < 4; i++)
- alu->src->swizzle[i] = i;
- }
+ ppir_alu_node *alu = ppir_node_to_alu(move);
+ alu->dest = *dest;
+ alu->num_src = 1;
+ ppir_node_target_assign(alu->src, node);
+ for (int s = 0; s < 4; s++)
+ alu->src->swizzle[s] = s;
- ppir_node_replace_pred(dep, move);
- ppir_node_replace_child(succ, node, move);
- }
+ ppir_node_foreach_succ_safe(node, dep) {
+ ppir_node_replace_pred(dep, move);
+ ppir_node_replace_child(succ, node, move);
}
- if (move) {
- ppir_node_add_dep(move, node);
- list_addtail(&move->list, &node->list);
- }
+ /* Need to be careful with changing src/dst type here:
+ * it has to be done *after* successors have their children
+ * replaced, otherwise ppir_node_replace_child() won't find
+ * matching src/dst and as result won't work
+ */
+ alu->src->type = dest->type = ppir_target_pipeline;
+ alu->src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
+ ppir_node_add_dep(move, node);
+ list_addtail(&move->list, &node->list);
return true;
}
if (!zero)
return false;
- list_addtail(&zero->node.list, &node->list);
-
zero->constant.value[0].f = 0;
zero->constant.num = 1;
- zero->dest.type = ppir_target_ssa;
+ zero->dest.type = ppir_target_pipeline;
+ zero->dest.pipeline = ppir_pipeline_reg_const0;
zero->dest.ssa.num_components = 1;
zero->dest.ssa.live_in = INT_MAX;
zero->dest.ssa.live_out = 0;
* comparision node into branch itself and use current
* way as a fallback for complex conditions.
*/
- branch->src[1].type = ppir_target_ssa;
- branch->src[1].ssa = &zero->dest.ssa;
+ ppir_node_target_assign(&branch->src[1], &zero->node);
branch->cond_gt = true;
branch->cond_lt = true;
ppir_node_add_dep(&branch->node, &zero->node);
+ list_addtail(&zero->node.list, &node->list);
return true;
}
}
}
- ppir_node_print_prog(comp);
return true;
}
if (ns->is_ssa) {
child = comp->var_nodes[ns->ssa->index];
+ /* Clone consts for each successor */
+ if (child->type == ppir_node_type_const)
+ child = ppir_node_clone_const(node->block, child);
+
ppir_node_add_dep(node, child);
}
else {
if (!ppir_lower_prog(comp))
goto err_out0;
+ ppir_node_print_prog(comp);
+
if (!ppir_node_to_instr(comp))
goto err_out0;
}
printf("====================\n");
}
+
+ppir_node *ppir_node_clone_const(ppir_block *block, ppir_node *node)
+{
+ ppir_const_node *cnode = ppir_node_to_const(node);
+ ppir_const_node *new_cnode = ppir_node_create(block, ppir_op_const, -1, 0);
+
+ if (!new_cnode)
+ return NULL;
+
+ list_addtail(&new_cnode->node.list, &block->node_list);
+
+ new_cnode->constant.num = cnode->constant.num;
+ for (int i = 0; i < cnode->constant.num; i++) {
+ new_cnode->constant.value[i] = cnode->constant.value[i];
+ }
+ new_cnode->dest.type = ppir_target_ssa;
+ new_cnode->dest.ssa.num_components = cnode->dest.ssa.num_components;
+ new_cnode->dest.ssa.live_in = INT_MAX;
+ new_cnode->dest.ssa.live_out = 0;
+ new_cnode->dest.write_mask = cnode->dest.write_mask;
+
+ return &new_cnode->node;
+}
return true;
}
-static bool insert_to_each_succ_instr(ppir_block *block, ppir_node *node)
-{
- ppir_dest *dest = ppir_node_get_dest(node);
- assert(dest->type == ppir_target_ssa);
-
- ppir_node *move = NULL;
-
- ppir_node_foreach_succ_safe(node, dep) {
- ppir_node *succ = dep->succ;
- assert(succ->type == ppir_node_type_alu ||
- succ->type == ppir_node_type_branch);
-
- if (!ppir_instr_insert_node(succ->instr, node)) {
- /* create a move node to insert for failed node */
- if (!move) {
- move = ppir_node_create(block, ppir_op_mov, -1, 0);
- if (unlikely(!move))
- return false;
-
- ppir_debug("node_to_instr create move %d for %d\n",
- move->index, node->index);
-
- ppir_alu_node *alu = ppir_node_to_alu(move);
- alu->dest = *dest;
- alu->num_src = 1;
- ppir_node_target_assign(alu->src, node);
- for (int i = 0; i < 4; i++)
- alu->src->swizzle[i] = i;
- }
-
- ppir_node_replace_pred(dep, move);
- ppir_node_replace_child(succ, node, move);
- }
- }
-
- if (move) {
- if (!create_new_instr(block, move))
- return false;
-
- ASSERTED bool insert_result =
- ppir_instr_insert_node(move->instr, node);
- assert(insert_result);
-
- ppir_node_add_dep(move, node);
- list_addtail(&move->list, &node->list);
- }
-
- /* dupliacte node for each successor */
-
- bool first = true;
- struct list_head dup_list;
- list_inithead(&dup_list);
-
- ppir_node_foreach_succ_safe(node, dep) {
- ppir_node *succ = dep->succ;
-
- if (first) {
- first = false;
- node->instr = succ->instr;
- continue;
- }
-
- if (succ->instr == node->instr)
- continue;
-
- list_for_each_entry(ppir_node, dup, &dup_list, list) {
- if (succ->instr == dup->instr) {
- ppir_node_replace_pred(dep, dup);
- continue;
- }
- }
-
- ppir_node *dup = ppir_node_create(block, node->op, -1, 0);
- if (unlikely(!dup))
- return false;
- list_addtail(&dup->list, &dup_list);
-
- ppir_debug("node_to_instr duplicate %s %d from %d\n",
- ppir_op_infos[dup->op].name, dup->index, node->index);
-
- ppir_instr *instr = succ->instr;
- dup->instr = instr;
- dup->instr_pos = node->instr_pos;
- ppir_node_replace_pred(dep, dup);
- }
-
- list_splicetail(&dup_list, &node->list);
-
- return true;
-}
-
/*
* If a node has a pipeline dest, schedule it in the same instruction as its
* successor.
return false;
break;
case ppir_node_type_const:
- if (!insert_to_each_succ_instr(block, node))
- return false;
+ /* Const nodes are supposed to go through do_node_to_instr_pipeline() */
+ assert(false);
break;
case ppir_node_type_store:
{
void ppir_node_replace_child(ppir_node *parent, ppir_node *old_child, ppir_node *new_child);
void ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src);
void ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred);
+ppir_node *ppir_node_clone_const(ppir_block *block, ppir_node *node);
static inline bool ppir_node_is_root(ppir_node *node)
{
return NULL;
}
+static inline ppir_src *ppir_node_get_src_for_pred(ppir_node *node, ppir_node *pred)
+{
+ for (int i = 0; i < ppir_node_get_src_num(node); i++) {
+ ppir_src *src = ppir_node_get_src(node, i);
+ if (src && src->node == pred)
+ return src;
+ }
+
+ return NULL;
+}
+
static inline void ppir_node_target_assign(ppir_src *src, ppir_node *node)
{
ppir_dest *dest = ppir_node_get_dest(node);