Module: Mesa
Branch: main
Commit: c38c119617a83d72a34b6f8e42db78029e6e9ece
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=c38c119617a83d72a34b6f8e42db78029e6e9ece

Author: Simon Perretta <[email protected]>
Date:   Fri Feb 17 14:59:47 2023 +0000

pvr: Add basic support for manual instruction grouping

Signed-off-by: Simon Perretta <[email protected]>
Acked-by: Frank Binns <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21474>

---

 .../rogue/passes/rogue_schedule_instr_groups.c     | 18 ++++--
 src/imagination/rogue/rogue.h                      |  7 +++
 src/imagination/rogue/rogue_encode.c               | 71 +++++++++++++++-------
 src/imagination/rogue/rogue_info.c                 |  2 +-
 src/imagination/rogue/rogue_isa.h                  |  2 +-
 src/imagination/rogue/rogue_print.c                |  3 +-
 6 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c 
b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
index 0ed103671a0..1587ec777f7 100644
--- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
+++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
@@ -840,6 +840,8 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, bool 
multi_instr_groups)
 
    rogue_lower_regs(shader);
 
+   rogue_instr_group *group;
+   bool grouping = false;
    unsigned g = 0;
    rogue_foreach_block (block, shader) {
       struct list_head instr_groups;
@@ -865,12 +867,20 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, 
bool multi_instr_groups)
             unreachable("Unsupported instruction type.");
          }
 
-         rogue_instr_group *group = rogue_instr_group_create(block, group_alu);
-         group->index = g++;
+         if (!grouping) {
+            group = rogue_instr_group_create(block, group_alu);
+            group->index = g++;
+         }
 
+         assert(group_alu == group->header.alu);
          rogue_move_instr_to_group(instr, group);
-         rogue_finalise_instr_group(group);
-         list_addtail(&group->link, &instr_groups);
+
+         grouping = instr->group_next;
+
+         if (!grouping) {
+            rogue_finalise_instr_group(group);
+            list_addtail(&group->link, &instr_groups);
+         }
       }
 
       list_replace(&instr_groups, &block->instrs);
diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h
index 5b5ce650876..b4b611c2243 100644
--- a/src/imagination/rogue/rogue.h
+++ b/src/imagination/rogue/rogue.h
@@ -450,10 +450,17 @@ typedef struct rogue_instr {
 
    rogue_block *block; /** Basic block containing this instruction. */
 
+   bool group_next; /** Group next instruction with this one. */
    unsigned index; /** Instruction index. */
    char *comment; /** Comment string. */
 } rogue_instr;
 
+static inline void rogue_set_instr_group_next(rogue_instr *instr,
+                                              bool group_next)
+{
+   instr->group_next = group_next;
+}
+
 #define rogue_foreach_instr_in_block(instr, block) \
    list_for_each_entry (rogue_instr, instr, &(block)->instrs, link)
 
diff --git a/src/imagination/rogue/rogue_encode.c 
b/src/imagination/rogue/rogue_encode.c
index c88839304be..cd8100d6e7b 100644
--- a/src/imagination/rogue/rogue_encode.c
+++ b/src/imagination/rogue/rogue_encode.c
@@ -70,6 +70,52 @@ static unsigned rogue_calc_da(const rogue_instr_group *group)
    return da;
 }
 
+#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type)
+static enum oporg rogue_calc_oporg(uint64_t alu_phases)
+{
+   bool P0 = !!(alu_phases & P(0));
+   bool P1 = !!(alu_phases & P(1));
+   bool P2 = !!(alu_phases & (P(2_PCK) | P(2_TST) | P(2_MOV)));
+   bool PBE = !!(alu_phases & P(BACKEND));
+
+   if (P0 && P1 && P2 && PBE)
+      return OPORG_P0_P1_P2_BE;
+   else if (P0 && !P1 && P2 && PBE)
+      return OPORG_P0_P2_BE;
+   else if (P0 && P1 && P2 && !PBE)
+      return OPORG_P0_P1_P2;
+   else if (P0 && !P1 && P2 && !PBE)
+      return OPORG_P0_P2;
+   else if (P0 && P1 && !P2 && !PBE)
+      return OPORG_P0_P1;
+   else if (!P0 && !P1 && !P2 && PBE)
+      return OPORG_BE;
+   else if (!P0 && !P1 && P2 && !PBE)
+      return OPORG_P2;
+   else if (P0 && !P1 && !P2 && !PBE)
+      return OPORG_P0;
+
+   unreachable("Invalid ALU phase combination.");
+}
+
+static enum opcnt rogue_calc_opcnt(uint64_t bitwise_phases)
+{
+   enum opcnt opcnt = 0;
+
+   if (bitwise_phases & P(0_BITMASK) || bitwise_phases & P(0_SHIFT1) ||
+       bitwise_phases & P(0_COUNT)) {
+      opcnt |= OPCNT_P0;
+   }
+
+   if (bitwise_phases & P(1_LOGICAL))
+      opcnt |= OPCNT_P1;
+
+   if (bitwise_phases & P(2_SHIFT2) || bitwise_phases & P(2_TEST))
+      opcnt |= OPCNT_P2;
+
+   return opcnt;
+}
+
 static void rogue_encode_instr_group_header(rogue_instr_group *group,
                                             struct util_dynarray *binary)
 {
@@ -116,31 +162,12 @@ static void 
rogue_encode_instr_group_header(rogue_instr_group *group,
    switch (group->header.alu) {
    case ROGUE_ALU_MAIN:
       h.alutype = ALUTYPE_MAIN;
-      /* TODO: Support multiple phase instructions. */
-#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type)
-      if (group->header.phases & P(0))
-         h.oporg = OPORG_P0;
-      if (group->header.phases & P(2_PCK) || group->header.phases & P(2_TST) ||
-          group->header.phases & P(2_MOV))
-         h.oporg = OPORG_P2;
-      if (group->header.phases & P(BACKEND))
-         h.oporg = OPORG_BE;
-#undef P
+      h.oporg = rogue_calc_oporg(group->header.phases);
       break;
 
    case ROGUE_ALU_BITWISE:
       h.alutype = ALUTYPE_BITWISE;
-#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type)
-      if (group->header.phases & P(0_BITMASK) ||
-          group->header.phases & P(0_SHIFT1) ||
-          group->header.phases & P(0_COUNT))
-         h.oporg |= OPCNT_P0;
-      if (group->header.phases & P(1_LOGICAL))
-         h.oporg |= OPCNT_P1;
-      if (group->header.phases & P(2_SHIFT2) ||
-          group->header.phases & P(2_TEST))
-         h.oporg |= OPCNT_P2;
-#undef P
+      h.opcnt = rogue_calc_opcnt(group->header.phases);
       break;
 
    case ROGUE_ALU_CONTROL:
@@ -180,13 +207,13 @@ static void 
rogue_encode_instr_group_header(rogue_instr_group *group,
 
    if (group->header.alu != ROGUE_ALU_CONTROL) {
       h.end = group->header.end;
-      /* h.crel = ; */ /* Unused for now */
       /* h.atom = ; */ /* Unused for now */
       h.rpt = group->header.repeat - 1;
    }
 
    util_dynarray_append_mem(binary, group->size.header, &h);
 }
+#undef P
 
 typedef union rogue_instr_encoding {
    rogue_alu_instr_encoding alu;
diff --git a/src/imagination/rogue/rogue_info.c 
b/src/imagination/rogue/rogue_info.c
index afe049c7fbb..0e1eb5b1a7c 100644
--- a/src/imagination/rogue/rogue_info.c
+++ b/src/imagination/rogue/rogue_info.c
@@ -574,7 +574,7 @@ const rogue_alu_op_info 
rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
       .supported_src_mods = {
          [0] = SM(ABS) | SM(NEG),
       },
-      .supported_dst_types = { [0] = T(REG) | T(REGARRAY), },
+      .supported_dst_types = { [0] = T(REG) | T(REGARRAY) | T(IO), },
       .supported_src_types = {
          [0] = T(REG),
       },
diff --git a/src/imagination/rogue/rogue_isa.h 
b/src/imagination/rogue/rogue_isa.h
index 88bfaeffe68..32c25e64289 100644
--- a/src/imagination/rogue/rogue_isa.h
+++ b/src/imagination/rogue/rogue_isa.h
@@ -1346,7 +1346,7 @@ typedef struct rogue_instr_group_header_encoding {
          unsigned ccext : 1;
          unsigned rpt : 2;
          unsigned atom : 1;
-         unsigned crel : 1;
+         unsigned : 1;
          unsigned alutype : 2;
          unsigned end : 1;
       } PACKED;
diff --git a/src/imagination/rogue/rogue_print.c 
b/src/imagination/rogue/rogue_print.c
index 7748385f343..49edbe3151e 100644
--- a/src/imagination/rogue/rogue_print.c
+++ b/src/imagination/rogue/rogue_print.c
@@ -592,7 +592,7 @@ static inline void rogue_print_instr_group(FILE *fp,
    fputs("{ ", fp);
 
    CYAN(fp);
-   fprintf(fp, "%s ", rogue_alu_str[group->header.alu]);
+   fprintf(fp, "%s", rogue_alu_str[group->header.alu]);
    RESET(fp);
 
    /* Print each instruction. */
@@ -600,6 +600,7 @@ static inline void rogue_print_instr_group(FILE *fp,
       const rogue_instr *instr = group->instrs[p];
       assert(instr);
 
+      fputs(" ", fp);
       rogue_print_instr_phase(fp, group->header.alu, p);
       fputs(": ", fp);
       rogue_print_instr(fp, instr);

Reply via email to