lima/ppir: introduce liveness internal live set
[mesa.git] / src / gallium / drivers / lima / ir / pp / lower.c
index 2244fc7dc3138802d89c290852a6371ce2ad31c2..f7c61df2b0ab533d4999ff9bc10c19b979443bab 100644 (file)
@@ -34,40 +34,41 @@ static bool ppir_lower_const(ppir_block *block, ppir_node *node)
       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;
-
-      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_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, dest);
-            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);
-      }
+   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 (move) {
-      ppir_node_add_dep(move, node);
-      list_addtail(&move->list, &node->list);
-   }
+   ppir_node *move = ppir_node_insert_mov(node);
+   if (unlikely(!move))
+      return false;
+
+   ppir_debug("lower const create move %d for %d\n",
+              move->index, node->index);
+
+   /* 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
+    */
+   ppir_src *mov_src = ppir_node_get_src(move, 0);
+   mov_src->type = dest->type = ppir_target_pipeline;
+   mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
 
    return true;
 }
@@ -89,27 +90,58 @@ static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
 
 static bool ppir_lower_load(ppir_block *block, ppir_node *node)
 {
-   ppir_node *move = ppir_node_create(block, ppir_op_mov, -1 , 0);
+   ppir_dest *dest = ppir_node_get_dest(node);
+   if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
+      ppir_node_delete(node);
+      return true;
+   }
+
+   /* load can have multiple successors in case if we duplicated load node
+    * that has load node in source
+    */
+   if ((ppir_node_has_single_src_succ(node) || ppir_node_is_root(node)) &&
+      dest->type != ppir_target_register) {
+      ppir_node *succ = ppir_node_first_succ(node);
+      switch (succ->type) {
+      case ppir_node_type_alu:
+      case ppir_node_type_branch: {
+         ppir_src *src = ppir_node_get_src_for_pred(succ, node);
+         /* Can consume uniforms directly */
+         src->type = dest->type = ppir_target_pipeline;
+         src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
+         return true;
+      }
+      default:
+         /* Create mov for everyone else */
+         break;
+      }
+   }
+
+   ppir_node *move = ppir_node_insert_mov(node);
    if (unlikely(!move))
       return false;
 
-   ppir_alu_node *alu = ppir_node_to_alu(move);
+   ppir_src *mov_src = ppir_node_get_src(move, 0);
+   mov_src->type = dest->type = ppir_target_pipeline;
+   mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
 
-   ppir_dest *dest = ppir_node_get_dest(node);
-   alu->dest = *dest;
-
-   ppir_node_replace_all_succ(move, node);
+   return true;
+}
 
-   dest->type = ppir_target_pipeline;
-   dest->pipeline = ppir_pipeline_reg_uniform;
+static bool ppir_lower_ddxy(ppir_block *block, ppir_node *node)
+{
+   assert(node->type == ppir_node_type_alu);
+   ppir_alu_node *alu = ppir_node_to_alu(node);
 
-   alu->num_src = 1;
-   ppir_node_target_assign(&alu->src[0], dest);
-   for (int i = 0; i < 4; i++)
-      alu->src->swizzle[i] = i;
+   alu->src[1] = alu->src[0];
+   if (node->op == ppir_op_ddx)
+      alu->src[1].negate = !alu->src[1].negate;
+   else if (node->op == ppir_op_ddy)
+      alu->src[0].negate = !alu->src[0].negate;
+   else
+      assert(0);
 
-   ppir_node_add_dep(move, node);
-   list_addtail(&move->list, &node->list);
+   alu->num_src = 2;
 
    return true;
 }
@@ -117,106 +149,53 @@ static bool ppir_lower_load(ppir_block *block, ppir_node *node)
 static bool ppir_lower_texture(ppir_block *block, ppir_node *node)
 {
    ppir_load_texture_node *load_tex = ppir_node_to_load_texture(node);
-
-   /* Create load_coords node */
-   ppir_load_node *load = ppir_node_create(block, ppir_op_load_coords, -1, 0);
-   if (!load)
-      return false;
-   list_addtail(&load->node.list, &node->list);
-
-   ppir_debug("%s create load_coords node %d for %d\n",
-              __FUNCTION__, load->node.index, node->index);
-
-   load->dest.type = ppir_target_pipeline;
-   load->dest.pipeline = ppir_pipeline_reg_discard;
-
-   load->src = load_tex->src_coords;
-
-   ppir_node_foreach_pred_safe(node, dep) {
-      ppir_node *pred = dep->pred;
-      ppir_node_remove_dep(dep);
-      ppir_node_add_dep(&load->node, pred);
+   ppir_dest *dest = ppir_node_get_dest(node);
+   ppir_node *src_coords = ppir_node_get_src(node, 0)->node;
+   ppir_load_node *load = NULL;
+
+   if (src_coords && ppir_node_has_single_src_succ(src_coords) &&
+       (src_coords->op == ppir_op_load_coords))
+      load = ppir_node_to_load(src_coords);
+   else {
+      /* Create load_coords node */
+      load = ppir_node_create(block, ppir_op_load_coords_reg, -1, 0);
+      if (!load)
+         return false;
+      list_addtail(&load->node.list, &node->list);
+
+      load->src = load_tex->src[0];
+      load->num_src = 1;
+      if (load_tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
+         load->num_components = 3;
+      else
+         load->num_components = 2;
+
+      ppir_debug("%s create load_coords node %d for %d\n",
+                 __FUNCTION__, load->node.index, node->index);
+
+      ppir_node_foreach_pred_safe(node, dep) {
+         ppir_node *pred = dep->pred;
+         ppir_node_remove_dep(dep);
+         ppir_node_add_dep(&load->node, pred, ppir_dep_src);
+      }
+      ppir_node_add_dep(node, &load->node, ppir_dep_src);
    }
 
-   ppir_node_add_dep(node, &load->node);
+   assert(load);
+   load_tex->src[0].type = load->dest.type = ppir_target_pipeline;
+   load_tex->src[0].pipeline = load->dest.pipeline = ppir_pipeline_reg_discard;
 
-   /* Create move node */
-   ppir_node *move = ppir_node_create(block, ppir_op_mov, -1 , 0);
+   /* Always create move node since there can be successors in other blocks */
+   ppir_node *move = ppir_node_insert_mov_all_blocks(node);
    if (unlikely(!move))
       return false;
 
-   ppir_alu_node *alu = ppir_node_to_alu(move);
-
-   ppir_dest *dest = ppir_node_get_dest(node);
-   alu->dest = *dest;
-
-   ppir_node_replace_all_succ(move, node);
-
-   dest->type = ppir_target_pipeline;
-   dest->pipeline = ppir_pipeline_reg_sampler;
-
-   alu->num_src = 1;
-   ppir_node_target_assign(&alu->src[0], dest);
-   for (int i = 0; i < 4; i++)
-      alu->src->swizzle[i] = i;
-
-   ppir_node_add_dep(move, node);
-   list_addtail(&move->list, &node->list);
-
-   return true;
-}
-
-static bool ppir_lower_sin_cos(ppir_block *block, ppir_node *node)
-{
-   ppir_alu_node *alu = ppir_node_to_alu(node);
+   ppir_debug("lower texture create move %d for %d\n",
+              move->index, node->index);
 
-   ppir_node *inv_2pi_node = ppir_node_create(block, ppir_op_const, -1, 0);
-   if (!inv_2pi_node)
-      return false;
-   list_addtail(&inv_2pi_node->list, &node->list);
-
-   /* For sin and cos, the input has to multiplied by the constant
-    * 1/(2*pi), presumably to simplify the hardware. */
-   ppir_const_node *inv_2pi_const = ppir_node_to_const(inv_2pi_node);
-   inv_2pi_const->constant.num = 1;
-   inv_2pi_const->constant.value[0].f = (1.0f/(2.0f * M_PI));
-
-   inv_2pi_const->dest.type = ppir_target_ssa;
-   inv_2pi_const->dest.ssa.num_components = 1;
-   inv_2pi_const->dest.ssa.live_in = INT_MAX;
-   inv_2pi_const->dest.ssa.live_out = 0;
-   inv_2pi_const->dest.write_mask = 0x01;
-
-   ppir_node *mul_node = ppir_node_create(block, ppir_op_mul, -1, 0);
-   if (!mul_node)
-      return false;
-   list_addtail(&mul_node->list, &node->list);
-
-   ppir_alu_node *mul_alu = ppir_node_to_alu(mul_node);
-   mul_alu->num_src = 2;
-   mul_alu->src[0] = alu->src[0];
-   mul_alu->src[1].type = ppir_target_ssa;
-   mul_alu->src[1].ssa = &inv_2pi_const->dest.ssa;
-
-   int num_components = alu->src[0].ssa->num_components;
-   mul_alu->dest.type = ppir_target_ssa;
-   mul_alu->dest.ssa.num_components = num_components;
-   mul_alu->dest.ssa.live_in = INT_MAX;
-   mul_alu->dest.ssa.live_out = 0;
-   mul_alu->dest.write_mask = u_bit_consecutive(0, num_components);
-
-   alu->src[0].type = ppir_target_ssa;
-   alu->src[0].ssa = &mul_alu->dest.ssa;
-   for (int i = 0; i < 4; i++)
-      alu->src->swizzle[i] = i;
-
-   ppir_node_foreach_pred_safe(node, dep) {
-      ppir_node *pred = dep->pred;
-      ppir_node_remove_dep(dep);
-      ppir_node_add_dep(mul_node, pred);
-   }
-   ppir_node_add_dep(node, mul_node);
-   ppir_node_add_dep(mul_node, inv_2pi_node);
+   ppir_src *mov_src=  ppir_node_get_src(move, 0);
+   mov_src->type = dest->type = ppir_target_pipeline;
+   mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
 
    return true;
 }
@@ -245,22 +224,20 @@ static bool ppir_lower_select(ppir_block *block, ppir_node *node)
    move_dest->pipeline = ppir_pipeline_reg_fmul;
    move_dest->write_mask = 1;
 
-   ppir_node_foreach_pred(node, dep) {
-      ppir_node *pred = dep->pred;
-      ppir_dest *dest = ppir_node_get_dest(pred);
-      if (ppir_node_target_equal(alu->src, dest)) {
-         ppir_node_replace_pred(dep, move);
-         ppir_node_add_dep(move, pred);
-      }
-   }
+   ppir_node *pred = alu->src[0].node;
+   ppir_dep *dep = ppir_dep_for_pred(node, pred);
+   if (dep)
+      ppir_node_replace_pred(dep, move);
+   else
+      ppir_node_add_dep(node, move, ppir_dep_src);
 
-   /* move must be the first pred of select node which make sure
-    * the float mul slot is free when node to instr
-    */
-   assert(ppir_node_first_pred(node) == move);
+   /* pred can be a register */
+   if (pred)
+      ppir_node_add_dep(move, pred, ppir_dep_src);
 
    src->swizzle[0] = 0;
-   ppir_node_target_assign(alu->src, move_dest);
+   ppir_node_target_assign(alu->src, move);
+
    return true;
 }
 
@@ -319,19 +296,21 @@ static bool ppir_lower_sat(ppir_block *block, ppir_node *node)
 static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
 {
    ppir_branch_node *branch = ppir_node_to_branch(node);
+
+   /* Unconditional branch */
+   if (branch->num_src == 0)
+      return true;
+
    ppir_const_node *zero = ppir_node_create(block, ppir_op_const, -1, 0);
 
    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;
    zero->dest.write_mask = 0x01;
 
    /* For now we're just comparing branch condition with 0,
@@ -339,13 +318,19 @@ static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
     * 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);
+
+   if (branch->negate)
+      branch->cond_eq = true;
+   else {
+      branch->cond_gt = true;
+      branch->cond_lt = true;
+   }
 
-   branch->cond_gt = true;
-   branch->cond_lt = true;
+   branch->num_src = 2;
 
-   ppir_node_add_dep(&branch->node, &zero->node);
+   ppir_node_add_dep(&branch->node, &zero->node, ppir_dep_src);
+   list_addtail(&zero->node.list, &node->list);
 
    return true;
 }
@@ -354,8 +339,8 @@ static bool (*ppir_lower_funcs[ppir_op_num])(ppir_block *, ppir_node *) = {
    [ppir_op_abs] = ppir_lower_abs,
    [ppir_op_neg] = ppir_lower_neg,
    [ppir_op_const] = ppir_lower_const,
-   [ppir_op_sin] = ppir_lower_sin_cos,
-   [ppir_op_cos] = ppir_lower_sin_cos,
+   [ppir_op_ddx] = ppir_lower_ddxy,
+   [ppir_op_ddy] = ppir_lower_ddxy,
    [ppir_op_lt] = ppir_lower_swap_args,
    [ppir_op_le] = ppir_lower_swap_args,
    [ppir_op_load_texture] = ppir_lower_texture,
@@ -377,6 +362,5 @@ bool ppir_lower_prog(ppir_compiler *comp)
       }
    }
 
-   ppir_node_print_prog(comp);
    return true;
 }