lima/ppir: do not assume single src for pipeline outputs
[mesa.git] / src / gallium / drivers / lima / ir / pp / ppir.h
index 3395a13ee564c438162373c1e2083dbd9d4cab36..dc76bfdc38aa62c67f75f96333a58a4c59c78850 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util/u_math.h"
 #include "util/list.h"
+#include "util/set.h"
 
 #include "ir/lima_ir.h"
 
@@ -53,6 +54,7 @@ typedef enum {
    ppir_op_normalize3,
    ppir_op_normalize4,
 
+   ppir_op_sel_cond,
    ppir_op_select,
 
    ppir_op_sin,
@@ -83,10 +85,6 @@ typedef enum {
    ppir_op_max,
    ppir_op_trunc,
 
-   ppir_op_dot2,
-   ppir_op_dot3,
-   ppir_op_dot4,
-
    ppir_op_and,
    ppir_op_or,
    ppir_op_xor,
@@ -102,8 +100,10 @@ typedef enum {
    ppir_op_load_uniform,
    ppir_op_load_varying,
    ppir_op_load_coords,
+   ppir_op_load_coords_reg,
    ppir_op_load_fragcoord,
    ppir_op_load_pointcoord,
+   ppir_op_load_frontface,
    ppir_op_load_texture,
    ppir_op_load_temp,
 
@@ -115,6 +115,9 @@ typedef enum {
    ppir_op_discard,
    ppir_op_branch,
 
+   ppir_op_undef,
+   ppir_op_dummy,
+
    ppir_op_num,
 } ppir_op;
 
@@ -136,8 +139,15 @@ typedef struct {
 
 extern const ppir_op_info ppir_op_infos[];
 
+typedef enum {
+   ppir_dep_src,
+   ppir_dep_write_after_read,
+   ppir_dep_sequence,
+} ppir_dep_type;
+
 typedef struct {
    void *pred, *succ;
+   ppir_dep_type type;
    struct list_head pred_link;
    struct list_head succ_link;
 } ppir_dep;
@@ -171,15 +181,15 @@ typedef enum {
 typedef struct ppir_reg {
    struct list_head list;
    int index;
+   int regalloc_index;
    int num_components;
+
    /* whether this reg has to start from the x component
     * of a full physical reg, this is true for reg used
-    * in load/store instr which has no swizzle field
-    */
+    * in load/store instr which has no swizzle field */
    bool is_head;
-   /* instr live range */
-   int live_in, live_out;
    bool spilled;
+   bool undef;
 } ppir_reg;
 
 typedef enum {
@@ -190,6 +200,7 @@ typedef enum {
 
 typedef struct ppir_src {
    ppir_target type;
+   ppir_node *node;
 
    union {
       ppir_reg *ssa;
@@ -246,6 +257,7 @@ typedef struct {
    int num_components;
    ppir_dest dest;
    ppir_src src;
+   int num_src;
 } ppir_load_node;
 
 typedef struct {
@@ -258,9 +270,13 @@ typedef struct {
 typedef struct {
    ppir_node node;
    ppir_dest dest;
-   ppir_src src_coords;
+   ppir_src src[2]; /* src[0] temporarily stores src_coords,
+                       not to be used after lowering */
+   int num_src;
    int sampler;
    int sampler_dim;
+   bool lod_bias_en;
+   bool explicit_lod;
 } ppir_load_texture_node;
 
 typedef struct {
@@ -284,6 +300,11 @@ enum ppir_instr_slot {
    PPIR_INSTR_SLOT_ALU_END = PPIR_INSTR_SLOT_ALU_COMBINE,
 };
 
+struct ppir_liveness {
+   ppir_reg *reg;
+   unsigned mask : 4;
+};
+
 typedef struct ppir_instr {
    struct list_head list;
    int index;
@@ -303,25 +324,47 @@ typedef struct ppir_instr {
    bool scheduled;
    int offset;
    int encode_size;
+
+   /* for liveness analysis */
+   struct ppir_liveness *live_in;
+   struct ppir_liveness *live_out;
+   /* live_internal is to mark registers only live within an
+    * instruction, without propagation */
+   struct ppir_liveness *live_internal;
+   struct set *live_in_set;
+   struct set *live_out_set;
+   struct set *live_internal_set;
 } ppir_instr;
 
 typedef struct ppir_block {
    struct list_head list;
    struct list_head node_list;
    struct list_head instr_list;
+
+   struct ppir_block *successors[2];
+
    struct ppir_compiler *comp;
 
    /* for scheduler */
    int sched_instr_index;
    int sched_instr_base;
+   int index;
+
+   /* for liveness analysis */
+   struct ppir_liveness *live_in;
+   struct ppir_liveness *live_out;
+   struct set *live_in_set;
+   struct set *live_out_set;
 } ppir_block;
 
 typedef struct {
    ppir_node node;
    ppir_src src[2];
+   int num_src;
    bool cond_gt;
    bool cond_eq;
    bool cond_lt;
+   bool negate;
    ppir_block *target;
 } ppir_branch_node;
 
@@ -330,6 +373,7 @@ struct lima_fs_shader_state;
 
 typedef struct ppir_compiler {
    struct list_head block_list;
+   struct hash_table_u64 *blocks;
    int cur_index;
    int cur_instr_index;
 
@@ -348,26 +392,40 @@ typedef struct ppir_compiler {
    /* for regalloc spilling debug */
    int force_spilling;
 
+   /* shaderdb */
+   int num_loops;
+   int num_spills;
+   int num_fills;
+
    ppir_block *discard_block;
+   ppir_block *current_block;
+   ppir_block *loop_break_block;
+   ppir_block *loop_cont_block;
 } ppir_compiler;
 
 void *ppir_node_create(ppir_block *block, ppir_op op, int index, unsigned mask);
-void ppir_node_add_dep(ppir_node *succ, ppir_node *pred);
+void ppir_node_add_dep(ppir_node *succ, ppir_node *pred, ppir_dep_type type);
 void ppir_node_remove_dep(ppir_dep *dep);
 void ppir_node_delete(ppir_node *node);
 void ppir_node_print_prog(ppir_compiler *comp);
 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);
+void ppir_delete_if_orphan(ppir_block *block, ppir_node *node);
+ppir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred);
+ppir_node *ppir_node_clone(ppir_block *block, ppir_node *node);
+/* Assumes that node successors are in the same block */
+ppir_node *ppir_node_insert_mov(ppir_node *node);
+ppir_node *ppir_node_insert_mov_all_blocks(ppir_node *node);
 
 static inline bool ppir_node_is_root(ppir_node *node)
 {
-   return list_empty(&node->succ_list);
+   return list_is_empty(&node->succ_list);
 }
 
 static inline bool ppir_node_is_leaf(ppir_node *node)
 {
-   return list_empty(&node->pred_list);
+   return list_is_empty(&node->pred_list);
 }
 
 static inline bool ppir_node_has_single_succ(ppir_node *node)
@@ -375,6 +433,8 @@ static inline bool ppir_node_has_single_succ(ppir_node *node)
    return list_is_singular(&node->succ_list);
 }
 
+bool ppir_node_has_single_src_succ(ppir_node *node);
+
 static inline ppir_node *ppir_node_first_succ(ppir_node *node)
 {
    return list_first_entry(&node->succ_list, ppir_dep, succ_link)->succ;
@@ -423,18 +483,92 @@ static inline ppir_dest *ppir_node_get_dest(ppir_node *node)
    }
 }
 
-static inline void ppir_node_target_assign(ppir_src *src, ppir_dest *dest)
+static inline int ppir_node_get_src_num(ppir_node *node)
 {
+   switch (node->type) {
+   case ppir_node_type_alu:
+      return ppir_node_to_alu(node)->num_src;
+   case ppir_node_type_branch:
+      return ppir_node_to_branch(node)->num_src;
+   case ppir_node_type_load:
+      return ppir_node_to_load(node)->num_src;
+   case ppir_node_type_load_texture:
+      return ppir_node_to_load_texture(node)->num_src;
+   case ppir_node_type_store:
+      return 1;
+   default:
+      return 0;
+   }
+
+   return 0;
+}
+
+static inline ppir_src *ppir_node_get_src(ppir_node *node, int idx)
+{
+   if (idx < 0 || idx >= ppir_node_get_src_num(node))
+      return NULL;
+
+   switch (node->type) {
+   case ppir_node_type_alu:
+      return &ppir_node_to_alu(node)->src[idx];
+   case ppir_node_type_branch:
+      return &ppir_node_to_branch(node)->src[idx];
+   case ppir_node_type_load_texture:
+      return &ppir_node_to_load_texture(node)->src[idx];
+   case ppir_node_type_load:
+      return &ppir_node_to_load(node)->src;
+   case ppir_node_type_store:
+      return &ppir_node_to_store(node)->src;
+   default:
+      break;
+   }
+
+   return NULL;
+}
+
+static inline ppir_reg *ppir_src_get_reg(ppir_src *src)
+{
+   switch (src->type) {
+   case ppir_target_ssa:
+      return src->ssa;
+   case ppir_target_register:
+      return src->reg;
+   default:
+      return NULL;
+   }
+}
+
+static inline ppir_reg *ppir_dest_get_reg(ppir_dest *dest)
+{
+   switch (dest->type) {
+   case ppir_target_ssa:
+      return &dest->ssa;
+   case ppir_target_register:
+      return dest->reg;
+   default:
+      return NULL;
+   }
+}
+
+static inline void ppir_node_target_assign(ppir_src *src, ppir_node *node)
+{
+   ppir_dest *dest = ppir_node_get_dest(node);
    src->type = dest->type;
    switch (src->type) {
    case ppir_target_ssa:
       src->ssa = &dest->ssa;
+      src->node = node;
       break;
    case ppir_target_register:
       src->reg = dest->reg;
+      /* Registers can be assigned from multiple nodes, so don't keep
+       * pointer to the node here
+       */
+      src->node = NULL;
       break;
    case ppir_target_pipeline:
       src->pipeline = dest->pipeline;
+      src->node = node;
       break;
    }
 }
@@ -454,9 +588,13 @@ static inline int ppir_target_get_src_reg_index(ppir_src *src)
 {
    switch (src->type) {
    case ppir_target_ssa:
-      return src->ssa->index;
+      if (src->ssa)
+         return src->ssa->index;
+      break;
    case ppir_target_register:
-      return src->reg->index;
+      if (src->reg)
+         return src->reg->index;
+      break;
    case ppir_target_pipeline:
       if (src->pipeline == ppir_pipeline_reg_discard)
          return 15 * 4;
@@ -482,6 +620,17 @@ static inline int ppir_target_get_dest_reg_index(ppir_dest *dest)
    return -1;
 }
 
+static inline int ppir_src_get_mask(ppir_src *src)
+{
+   ppir_reg *reg = ppir_src_get_reg(src);
+   int mask = 0;
+
+   for (int i = 0; i < reg->num_components; i++)
+      mask |= (1 << src->swizzle[i]);
+
+   return mask;
+}
+
 static inline bool ppir_target_is_scaler(ppir_dest *dest)
 {
    switch (dest->type) {
@@ -526,12 +675,12 @@ void ppir_instr_insert_mul_node(ppir_node *add, ppir_node *mul);
 
 static inline bool ppir_instr_is_root(ppir_instr *instr)
 {
-   return list_empty(&instr->succ_list);
+   return list_is_empty(&instr->succ_list);
 }
 
 static inline bool ppir_instr_is_leaf(ppir_instr *instr)
 {
-   return list_empty(&instr->pred_list);
+   return list_is_empty(&instr->pred_list);
 }
 
 bool ppir_lower_prog(ppir_compiler *comp);
@@ -539,5 +688,6 @@ bool ppir_node_to_instr(ppir_compiler *comp);
 bool ppir_schedule_prog(ppir_compiler *comp);
 bool ppir_regalloc_prog(ppir_compiler *comp);
 bool ppir_codegen_prog(ppir_compiler *comp);
+void ppir_liveness_analysis(ppir_compiler *comp);
 
 #endif