aco: improve support for s_sendmsg
authorRhys Perry <pendingchaos02@gmail.com>
Mon, 14 Oct 2019 16:21:04 +0000 (17:21 +0100)
committerMarge Bot <eric+marge@anholt.net>
Fri, 24 Jan 2020 13:35:07 +0000 (13:35 +0000)
In particular, the messages needed for GS.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2421>

src/amd/compiler/aco_builder_h.py
src/amd/compiler/aco_insert_NOPs.cpp
src/amd/compiler/aco_insert_waitcnt.cpp
src/amd/compiler/aco_print_ir.cpp

index b8854810e470a9f29f27adb5c6037b2bb1416d45..18e4bf752ec18c37ab14e1a5783a7eae9cea16a3 100644 (file)
@@ -78,6 +78,33 @@ ds_pattern_bitmode(unsigned and_mask, unsigned or_mask, unsigned xor_mask)
 
 aco_ptr<Instruction> create_s_mov(Definition dst, Operand src);
 
+enum sendmsg {
+   sendmsg_none = 0,
+   _sendmsg_gs = 2,
+   _sendmsg_gs_done = 3,
+   sendmsg_save_wave = 4,
+   sendmsg_stall_wave_gen = 5,
+   sendmsg_halt_waves = 6,
+   sendmsg_ordered_ps_done = 7,
+   sendmsg_early_prim_dealloc = 8,
+   sendmsg_gs_alloc_req = 9,
+   sendmsg_id_mask = 0xf,
+};
+
+inline sendmsg
+sendmsg_gs(bool cut, bool emit, unsigned stream)
+{
+    assert(stream < 4);
+    return (sendmsg)((unsigned)_sendmsg_gs | (cut << 4) | (emit << 5) | (stream << 8));
+}
+
+inline sendmsg
+sendmsg_gs_done(bool cut, bool emit, unsigned stream)
+{
+    assert(stream < 4);
+    return (sendmsg)((unsigned)_sendmsg_gs_done | (cut << 4) | (emit << 5) | (stream << 8));
+}
+
 class Builder {
 public:
    struct Result {
index 1ead0c04da5264700e18df32fc44553cb720fcdf..b9eaaed96db0697f85cca5208cd93d1124ef0741 100644 (file)
@@ -378,6 +378,14 @@ int handle_instruction_gfx8_9(NOP_ctx_gfx8_9& ctx, aco_ptr<Instruction>& instr,
             }
          }
       }
+   } else if (instr->format == Format::SOPP) {
+      if (instr->opcode == aco_opcode::s_sendmsg && new_idx > 0) {
+         aco_ptr<Instruction>& pred = new_instructions.back();
+         if (pred->isSALU() &&
+             !pred->definitions.empty() &&
+             pred->definitions[0].physReg() == m0)
+            return 1;
+      }
    }
 
    return 0;
index a8343d1889430dbac6a3f99e079f628d829fd1c0..b74d5f57c25553146b700facf2a00622044375ac 100644 (file)
@@ -65,6 +65,7 @@ enum wait_event : uint16_t {
    event_exp_mrt_null = 1 << 8,
    event_gds_gpr_lock = 1 << 9,
    event_vmem_gpr_lock = 1 << 10,
+   event_sendmsg = 1 << 11,
 };
 
 enum counter_type : uint8_t {
@@ -75,7 +76,7 @@ enum counter_type : uint8_t {
 };
 
 static const uint16_t exp_events = event_exp_pos | event_exp_param | event_exp_mrt_null | event_gds_gpr_lock | event_vmem_gpr_lock;
-static const uint16_t lgkm_events = event_smem | event_lds | event_gds | event_flat;
+static const uint16_t lgkm_events = event_smem | event_lds | event_gds | event_flat | event_sendmsg;
 static const uint16_t vm_events = event_vmem | event_flat;
 static const uint16_t vs_events = event_vmem_store;
 
@@ -85,6 +86,7 @@ uint8_t get_counters_for_event(wait_event ev)
    case event_smem:
    case event_lds:
    case event_gds:
+   case event_sendmsg:
       return counter_lgkm;
    case event_vmem:
       return counter_vm;
@@ -204,7 +206,7 @@ struct wait_entry {
 
       if (counter == counter_lgkm) {
          imm.lgkm = wait_imm::unset_counter;
-         events &= ~(event_smem | event_lds | event_gds);
+         events &= ~(event_smem | event_lds | event_gds | event_sendmsg);
       }
 
       if (counter == counter_vm) {
@@ -685,6 +687,11 @@ void gen(Instruction* instr, wait_ctx& ctx)
       }
       break;
    }
+   case Format::SOPP: {
+      if (instr->opcode == aco_opcode::s_sendmsg ||
+          instr->opcode == aco_opcode::s_sendmsghalt)
+         update_counters(ctx, event_sendmsg, get_barrier_interaction(instr));
+   }
    default:
       break;
    }
index 81711a278c90a65f4ac31b0a9380109b18e89e1e..c17845c082d26454ce35e801948573f0add46c5c 100644 (file)
@@ -192,6 +192,41 @@ static void print_instr_format_specific(struct Instruction *instr, FILE *output)
       case aco_opcode::s_set_gpr_idx_off: {
          break;
       }
+      case aco_opcode::s_sendmsg: {
+         unsigned id = imm & sendmsg_id_mask;
+         switch (id) {
+         case sendmsg_none:
+            fprintf(output, " sendmsg(MSG_NONE)");
+            break;
+         case _sendmsg_gs:
+            fprintf(output, " sendmsg(gs%s%s, %u)",
+                    imm & 0x10 ? ", cut" : "", imm & 0x20 ? ", emit" : "", imm >> 8);
+            break;
+         case _sendmsg_gs_done:
+            fprintf(output, " sendmsg(gs_done%s%s, %u)",
+                    imm & 0x10 ? ", cut" : "", imm & 0x20 ? ", emit" : "", imm >> 8);
+            break;
+         case sendmsg_save_wave:
+            fprintf(output, " sendmsg(save_wave)");
+            break;
+         case sendmsg_stall_wave_gen:
+            fprintf(output, " sendmsg(stall_wave_gen)");
+            break;
+         case sendmsg_halt_waves:
+            fprintf(output, " sendmsg(halt_waves)");
+            break;
+         case sendmsg_ordered_ps_done:
+            fprintf(output, " sendmsg(ordered_ps_done)");
+            break;
+         case sendmsg_early_prim_dealloc:
+            fprintf(output, " sendmsg(early_prim_dealloc)");
+            break;
+         case sendmsg_gs_alloc_req:
+            fprintf(output, " sendmsg(gs_alloc_req)");
+            break;
+         }
+         break;
+      }
       default: {
          if (imm)
             fprintf(output, " imm:%u", imm);