r600/sfn: Handle R600 scratch read
authorGert Wollny <gert.wollny@collabora.com>
Tue, 16 Aug 2022 07:59:02 +0000 (09:59 +0200)
committerMarge Bot <emma+marge@anholt.net>
Fri, 19 Aug 2022 08:37:42 +0000 (08:37 +0000)
Fixes: 33765aa92aa5c150873fc210e9d6c1fe22cf8646
     r600/sfn: Enable NIR for pre RG hardware

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18130>

14 files changed:
src/gallium/drivers/r600/sfn/sfn_assembler.cpp
src/gallium/drivers/r600/sfn/sfn_instr.cpp
src/gallium/drivers/r600/sfn/sfn_instr.h
src/gallium/drivers/r600/sfn/sfn_instr_alu.h
src/gallium/drivers/r600/sfn/sfn_instr_export.cpp
src/gallium/drivers/r600/sfn/sfn_instr_export.h
src/gallium/drivers/r600/sfn/sfn_instrfactory.cpp
src/gallium/drivers/r600/sfn/sfn_liverangeevaluator.cpp
src/gallium/drivers/r600/sfn/sfn_optimizer.cpp
src/gallium/drivers/r600/sfn/sfn_peephole.cpp
src/gallium/drivers/r600/sfn/sfn_scheduler.cpp
src/gallium/drivers/r600/sfn/sfn_shader.cpp
src/gallium/drivers/r600/sfn/sfn_shader.h
src/gallium/drivers/r600/sfn/tests/sfn_instrfromstring_test.cpp

index cfb7d72..00197d0 100644 (file)
@@ -58,7 +58,7 @@ public:
    void visit(const Block& instr) override;
    void visit(const IfInstr& instr) override;
    void visit(const ControlFlowInstr& instr) override;
-   void visit(const WriteScratchInstr& instr) override;
+   void visit(const ScratchIOInstr& instr) override;
    void visit(const StreamOutInstr& instr) override;
    void visit(const MemRingOutInstr& instr) override;
    void visit(const EmitVertexInstr& instr) override;
@@ -535,7 +535,7 @@ void AssamblerVisitor::visit(const ExportInstr& exi)
    }
 }
 
-void AssamblerVisitor::visit(const WriteScratchInstr& instr)
+void AssamblerVisitor::visit(const ScratchIOInstr& instr)
 {
    clear_states(sf_all);
 
@@ -546,27 +546,27 @@ void AssamblerVisitor::visit(const WriteScratchInstr& instr)
    cf.op = CF_OP_MEM_SCRATCH;
    cf.elem_size = 3;
    cf.gpr = instr.value().sel();
-   cf.mark = 1;
-   cf.comp_mask = instr.write_mask();
+   cf.mark = !instr.is_read();
+   cf.comp_mask = instr.is_read() ? 0xf : instr.write_mask();
    cf.swizzle_x = 0;
    cf.swizzle_y = 1;
    cf.swizzle_z = 2;
    cf.swizzle_w = 3;
    cf.burst_count = 1;
 
+   assert(!instr.is_read() || m_bc->gfx_level < R700);
+
    if (instr.address()) {
-      cf.type = 3;
+      cf.type = instr.is_read() || m_bc->gfx_level > R600 ? 3 : 1;
       cf.index_gpr = instr.address()->sel();
 
       /* The docu seems to be wrong here: In indirect addressing the
        * address_base seems to be the array_size */
       cf.array_size = instr.array_size();
    } else {
-      cf.type = 2;
+      cf.type = instr.is_read() || m_bc->gfx_level > R600 ? 2 : 0;
       cf.array_base = instr.location();
    }
-   /* This should be 0, but the address calculation is apparently wrong */
-
 
    if (r600_bytecode_add_output(m_bc, &cf)){
       R600_ERR("shader_from_nir: Error creating SCRATCH_WR assembly instruction\n");
index 28d3d73..cbc3b3a 100644 (file)
@@ -458,7 +458,7 @@ public:
    DECLARE_MEMBER(Block);
    DECLARE_MEMBER(ControlFlowInstr);
    DECLARE_MEMBER(IfInstr);
-   DECLARE_MEMBER(WriteScratchInstr);
+   DECLARE_MEMBER(ScratchIOInstr);
    DECLARE_MEMBER(StreamOutInstr);
    DECLARE_MEMBER(MemRingOutInstr);
    DECLARE_MEMBER(EmitVertexInstr);
@@ -504,7 +504,7 @@ public:
       m_comparer = InstrComparer(&instr);
    }
 
-   void visit(const WriteScratchInstr& instr) override {
+   void visit(const ScratchIOInstr& instr) override {
       m_comparer = InstrComparer(&instr);
    }
 
index 39bd36d..a715305 100644 (file)
@@ -45,7 +45,7 @@ class ExportInstr;
 class FetchInstr;
 class ControlFlowInstr;
 class IfInstr;
-class WriteScratchInstr;
+class ScratchIOInstr;
 class StreamOutInstr;
 class MemRingOutInstr;
 class EmitVertexInstr;
@@ -286,7 +286,7 @@ public:
    virtual void visit(const Block& instr) = 0;
    virtual void visit(const ControlFlowInstr& instr) = 0;
    virtual void visit(const IfInstr& instr) = 0;
-   virtual void visit(const WriteScratchInstr& instr) = 0;
+   virtual void visit(const ScratchIOInstr& instr) = 0;
    virtual void visit(const StreamOutInstr& instr) = 0;
    virtual void visit(const MemRingOutInstr& instr) = 0;
    virtual void visit(const EmitVertexInstr& instr) = 0;
@@ -307,7 +307,7 @@ public:
    virtual void visit(Block *instr) = 0;
    virtual void visit(ControlFlowInstr *instr) = 0;
    virtual void visit(IfInstr *instr) = 0;
-   virtual void visit(WriteScratchInstr *instr) = 0;
+   virtual void visit(ScratchIOInstr *instr) = 0;
    virtual void visit(StreamOutInstr *instr) = 0;
    virtual void visit(MemRingOutInstr *instr) = 0;
    virtual void visit(EmitVertexInstr *instr) = 0;
index b1ed854..075c0e1 100644 (file)
@@ -204,7 +204,7 @@ public:
    void visit(ExportInstr *instr) override {(void)instr;}
    void visit(FetchInstr *instr) override {(void)instr;}
    void visit(ControlFlowInstr *instr) override {(void)instr;}
-   void visit(WriteScratchInstr *instr) override {(void)instr;}
+   void visit(ScratchIOInstr *instr) override {(void)instr;}
    void visit(StreamOutInstr *instr) override {(void)instr;}
    void visit(MemRingOutInstr *instr) override {(void)instr;}
    void visit(EmitVertexInstr *instr) override {(void)instr;}
index 00826ed..5d4a3b7 100644 (file)
@@ -147,40 +147,52 @@ ExportInstr::Pointer ExportInstr::from_string_impl(std::istream& is, ValueFactor
    return new ExportInstr( type, pos, value);
 }
 
-WriteScratchInstr::WriteScratchInstr(const RegisterVec4& value, PRegister addr,
-                                     int align, int align_offset, int writemask, int array_size):
+ScratchIOInstr::ScratchIOInstr(const RegisterVec4& value, PRegister addr,
+                               int align, int align_offset, int writemask,
+                               int array_size, bool is_read):
    WriteOutInstr(value),
    m_address(addr),
    m_align(align),
    m_align_offset(align_offset),
    m_writemask(writemask),
-   m_array_size(array_size - 1)
+   m_array_size(array_size - 1),
+   m_read(is_read)
 {
    addr->add_use(this);
+   if (m_read) {
+      for (int i = 0; i < 4; ++i)
+         value[i]->add_parent(this);
+   }
 }
 
-WriteScratchInstr::WriteScratchInstr(const RegisterVec4& value, int loc,
-                                     int align, int align_offset,int writemask):
+ScratchIOInstr::ScratchIOInstr(const RegisterVec4& value, int loc,
+                               int align, int align_offset,int writemask,
+                               bool is_read):
    WriteOutInstr(value),
    m_loc(loc),
    m_align(align),
    m_align_offset(align_offset),
-   m_writemask(writemask)
+   m_writemask(writemask),
+   m_read(is_read)
 {
+   if (m_read) {
 
+      for (int i = 0; i < 4; ++i)
+         value[i]->add_parent(this);
+   }
 }
 
-void WriteScratchInstr::accept(ConstInstrVisitor& visitor) const
+void ScratchIOInstr::accept(ConstInstrVisitor& visitor) const
 {
    visitor.visit(*this);
 }
 
-void WriteScratchInstr::accept(InstrVisitor& visitor)
+void ScratchIOInstr::accept(InstrVisitor& visitor)
 {
    visitor.visit(this);
 }
 
-bool WriteScratchInstr::is_equal_to(const WriteScratchInstr& lhs) const
+bool ScratchIOInstr::is_equal_to(const ScratchIOInstr& lhs) const
 {
    if (m_address) {
       if (!lhs.m_address)
@@ -198,28 +210,40 @@ bool WriteScratchInstr::is_equal_to(const WriteScratchInstr& lhs) const
          value().sel() == lhs.value().sel();
 }
 
-bool WriteScratchInstr::do_ready() const
+bool ScratchIOInstr::do_ready() const
 {
-   return value().ready(block_id(), index()) &&
-         (!m_address || m_address->ready(block_id(), index()));
+   bool address_ready = !m_address || m_address->ready(block_id(), index());
+   if (is_read())
+      return address_ready;
+   else
+      return address_ready && value().ready(block_id(), index());
 }
 
-void WriteScratchInstr::do_print(std::ostream& os) const
+void ScratchIOInstr::do_print(std::ostream& os) const
 {
    char buf[6] = {0};
 
-   os << "WRITE_SCRATCH ";
+   os << (is_read() ? "READ_SCRATCH " : "WRITE_SCRATCH ");
+
+   if (is_read()) {
+      os << (value()[0]->is_ssa() ? " S" : " R")
+         << value().sel() << "." << writemask_to_swizzle(m_writemask, buf)
+         << " ";
+   }
+
    if (m_address)
       os << "@" << *m_address << "[" << m_array_size + 1<<"]";
    else
       os << m_loc;
 
-   os << (value()[0]->is_ssa() ? " S" : " R")
-      << value().sel() << "." << writemask_to_swizzle(m_writemask, buf)
-      << " " << "AL:" << m_align << " ALO:" << m_align_offset;
+   if (!is_read())
+      os << (value()[0]->is_ssa() ? " S" : " R")
+            << value().sel() << "." << writemask_to_swizzle(m_writemask, buf);
+
+   os << " " << "AL:" << m_align << " ALO:" << m_align_offset;
 }
 
-auto WriteScratchInstr::from_string(std::istream& is, ValueFactory &vf) -> Pointer
+auto ScratchIOInstr::from_string(std::istream& is, ValueFactory &vf) -> Pointer
 {
    string loc_str;
    string value_str;
@@ -261,10 +285,10 @@ auto WriteScratchInstr::from_string(std::istream& is, ValueFactory &vf) -> Point
       loc_ss >> array_size;
       loc_ss >> c;
       assert(c == ']');
-      return new WriteScratchInstr(value, addr_reg->as_register(), align, align_offset, writemask, array_size);
+      return new ScratchIOInstr(value, addr_reg->as_register(), align, align_offset, writemask, array_size);
    } else {
       loc_ss >> offset;
-      return new WriteScratchInstr(value, offset, align, align_offset, writemask);
+      return new ScratchIOInstr(value, offset, align, align_offset, writemask);
    }
 }
 
index c88a4e3..d19580a 100644 (file)
@@ -90,23 +90,25 @@ private:
    bool m_is_last;
 };
 
-class WriteScratchInstr : public WriteOutInstr {
+class ScratchIOInstr : public WriteOutInstr {
 public:
-   WriteScratchInstr(const RegisterVec4& value, PRegister addr,
-                     int align, int align_offset, int writemask, int array_size);
-   WriteScratchInstr(const RegisterVec4& value, int addr,  int align, int align_offset,
-                     int writemask);
+   ScratchIOInstr(const RegisterVec4& value, PRegister addr,
+                  int align, int align_offset, int writemask, int array_size,
+                  bool is_read = false);
+   ScratchIOInstr(const RegisterVec4& value, int addr,  int align, int align_offset,
+                  int writemask, bool is_read = false);
 
    void accept(ConstInstrVisitor& visitor) const override;
    void accept(InstrVisitor& visitor) override;
 
-   bool is_equal_to(const WriteScratchInstr& lhs) const;
+   bool is_equal_to(const ScratchIOInstr& lhs) const;
 
    unsigned location() const { return m_loc;};
    int write_mask() const { return m_writemask;}
    auto address() const { return m_address;}
    bool indirect() const { return !!m_address;}
    int array_size() const { return m_array_size;}
+   bool is_read() const {return m_read; }
 
    static auto from_string(std::istream& is, ValueFactory &vf) -> Pointer;
 private:
@@ -120,6 +122,7 @@ private:
    unsigned m_align_offset;
    unsigned m_writemask;
    int m_array_size{0};
+   bool m_read{false};
 };
 
 class StreamOutInstr: public WriteOutInstr {
index d66eb7f..e28446f 100644 (file)
@@ -92,7 +92,7 @@ PInst InstrFactory::from_string(const std::string& s, int nesting_depth)
    } else if (type == "IF") {
       result = IfInstr::from_string(is, m_value_factory);
    } else if (type == "WRITE_SCRATCH") {
-      result = WriteScratchInstr::from_string(is, m_value_factory);
+      result = ScratchIOInstr::from_string(is, m_value_factory);
    } else if (type == "MEM_RING") {
       result = MemRingOutInstr::from_string(is, m_value_factory);
    } else if (type == "EMIT_VERTEX") {
index b62aad1..cd8b113 100644 (file)
@@ -53,7 +53,7 @@ public:
    void visit(Block *instr) override;
    void visit(ControlFlowInstr *instr) override;
    void visit(IfInstr *instr) override;
-   void visit(WriteScratchInstr *instr) override;
+   void visit(ScratchIOInstr *instr) override;
    void visit(StreamOutInstr *instr) override;
    void visit(MemRingOutInstr *instr) override;
    void visit(EmitVertexInstr *instr) override {(void)instr;}
@@ -287,12 +287,15 @@ void LiveRangeInstrVisitor::visit(Block *instr)
    sfn_log << SfnLog::merge << "End block\n";
 }
 
-void LiveRangeInstrVisitor::visit(WriteScratchInstr *instr)
+void LiveRangeInstrVisitor::visit(ScratchIOInstr *instr)
 {
    auto& src = instr->value();
    for (int i = 0; i < 4; ++i) {
       if ((1 << i) & instr->write_mask()) {
-         record_read(src[i], LiveRangeEntry::use_unspecified);
+         if (instr->is_read())
+            record_write(src[i]);
+         else
+            record_read(src[i], LiveRangeEntry::use_unspecified);
       }
    }
 
index 18fb4e4..4325edf 100644 (file)
@@ -77,7 +77,7 @@ public:
 
    void visit(ControlFlowInstr *instr) override {(void)instr;};
    void visit(IfInstr *instr) override {(void)instr;};
-   void visit(WriteScratchInstr *instr) override {(void)instr;};
+   void visit(ScratchIOInstr *instr) override {(void)instr;};
    void visit(StreamOutInstr *instr) override {(void)instr;};
    void visit(MemRingOutInstr *instr) override {(void)instr;};
    void visit(EmitVertexInstr *instr) override {(void)instr;};
@@ -249,7 +249,7 @@ public:
    void visit(Block *instr) override;
    void visit(ControlFlowInstr *instr) override {(void)instr;}
    void visit(IfInstr *instr) override {(void)instr;}
-   void visit(WriteScratchInstr *instr) override {(void)instr;}
+   void visit(ScratchIOInstr *instr) override {(void)instr;}
    void visit(StreamOutInstr *instr) override {(void)instr;}
    void visit(MemRingOutInstr *instr) override {(void)instr;}
    void visit(EmitVertexInstr *instr) override {(void)instr;}
@@ -277,7 +277,7 @@ public:
    void visit(Block *instr) override;
    void visit(ControlFlowInstr *instr) override {(void)instr;}
    void visit(IfInstr *instr) override {(void)instr;}
-   void visit(WriteScratchInstr *instr) override {(void)instr;}
+   void visit(ScratchIOInstr *instr) override {(void)instr;}
    void visit(StreamOutInstr *instr) override {(void)instr;}
    void visit(MemRingOutInstr *instr) override {(void)instr;}
    void visit(EmitVertexInstr *instr) override {(void)instr;}
@@ -493,7 +493,7 @@ public:
    void visit(Block *instr) override;
    void visit(ControlFlowInstr *instr) override;
    void visit(IfInstr *instr) override;
-   void visit(WriteScratchInstr *instr) override;
+   void visit(ScratchIOInstr *instr) override;
    void visit(StreamOutInstr *instr) override;
    void visit(MemRingOutInstr *instr) override;
    void visit(EmitVertexInstr *instr) override {(void)instr;}
@@ -525,7 +525,7 @@ void SimplifySourceVecVisitor::visit(TexInstr *instr)
    }
 }
 
-void SimplifySourceVecVisitor::visit(WriteScratchInstr *instr)
+void SimplifySourceVecVisitor::visit(ScratchIOInstr *instr)
 {
    (void) instr;
 }
index a2e5fe3..0650312 100644 (file)
@@ -39,7 +39,7 @@ public:
    void visit(Block *instr) override;
    void visit(ControlFlowInstr *instr) override {(void)instr;}
    void visit(IfInstr *instr) override;
-   void visit(WriteScratchInstr *instr) override {(void)instr;}
+   void visit(ScratchIOInstr *instr) override {(void)instr;}
    void visit(StreamOutInstr *instr) override {(void)instr;}
    void visit(MemRingOutInstr *instr) override {(void)instr;}
    void visit(EmitVertexInstr *instr) override {(void)instr;}
index a80cc92..6c95c77 100644 (file)
@@ -87,7 +87,7 @@ public:
       m_cf_instr = instr;
    }
 
-   void visit(WriteScratchInstr *instr) override {
+   void visit(ScratchIOInstr *instr) override {
       mem_write_instr.push_back(instr);
    }
 
index f477d36..ce2ca43 100644 (file)
@@ -932,7 +932,7 @@ bool Shader::emit_store_scratch(nir_intrinsic_instr *intr)
    int align = nir_intrinsic_align_mul(intr);
    int align_offset = nir_intrinsic_align_offset(intr);
 
-   WriteScratchInstr *ws_ir = nullptr;
+   ScratchIOInstr *ws_ir = nullptr;
 
    int offset = -1;
    if (address->as_literal()) {
@@ -946,14 +946,14 @@ bool Shader::emit_store_scratch(nir_intrinsic_instr *intr)
    }
 
    if (offset >= 0) {
-      ws_ir = new WriteScratchInstr(value, offset, align, align_offset, writemask);
+      ws_ir = new ScratchIOInstr(value, offset, align, align_offset, writemask);
    } else {
       auto addr_temp  = vf.temp_register(0);      
       auto load_addr = new AluInstr(op1_mov, addr_temp, address, AluInstr::last_write);
       load_addr->set_alu_flag(alu_no_schedule_bias);
       emit_instruction(load_addr);
 
-      ws_ir = new WriteScratchInstr(value, addr_temp, align, align_offset, writemask, m_scratch_size);
+      ws_ir = new ScratchIOInstr(value, addr_temp, align, align_offset, writemask, m_scratch_size);
    }
    emit_instruction(ws_ir);
 
@@ -964,18 +964,48 @@ bool Shader::emit_store_scratch(nir_intrinsic_instr *intr)
 bool Shader::emit_load_scratch(nir_intrinsic_instr *intr)
 {
    auto addr = value_factory().src(intr->src[0], 0);
+   auto dest = value_factory().dest_vec4(intr->dest, pin_group);
 
-   RegisterVec4::Swizzle dest_swz = {7,7,7,7};
+   if (chip_class() >= ISA_CC_R700) {
+      RegisterVec4::Swizzle dest_swz = {7,7,7,7};
 
-   for (unsigned i = 0; i < intr->num_components; ++i)
-      dest_swz[i] = i;
+      for (unsigned i = 0; i < intr->num_components; ++i)
+         dest_swz[i] = i;
 
-   auto dest = value_factory().dest_vec4(intr->dest, pin_group);
+      auto *ir = new LoadFromScratch(dest, dest_swz, addr, m_scratch_size);
+      emit_instruction(ir);
+      chain_scratch_read(ir);
+   } else {
+      int align = nir_intrinsic_align_mul(intr);
+      int align_offset = nir_intrinsic_align_offset(intr);
+
+
+      int offset = -1;
+      if (addr->as_literal()) {
+         offset = addr->as_literal()->value();
+      } else if (addr->as_inline_const()) {
+         auto il = addr->as_inline_const();
+         if (il->sel() == ALU_SRC_0)
+            offset = 0;
+         else if (il->sel() == ALU_SRC_1_INT)
+            offset = 1;
+      }
 
-   auto ir = new LoadFromScratch(dest, dest_swz, addr, m_scratch_size);
-   emit_instruction(ir);
+      ScratchIOInstr *ir = nullptr;
+      if (offset >= 0) {
+         ir = new ScratchIOInstr(dest, offset, align, align_offset, 0xf, true);
+      } else {
+         auto addr_temp  = value_factory().temp_register(0);
+         auto load_addr = new AluInstr(op1_mov, addr_temp, addr, AluInstr::last_write);
+         load_addr->set_alu_flag(alu_no_schedule_bias);
+         emit_instruction(load_addr);
+
+         ir = new ScratchIOInstr(dest, addr_temp, align, align_offset, 0xf,
+                                 m_scratch_size, true);
+      }
+      emit_instruction(ir);
+   }
 
-   chain_scratch_read(ir);
 
    m_flags.set(sh_needs_scratch_space);
 
@@ -1033,7 +1063,7 @@ bool Shader::emit_wait_ack()
    return true;
 }
 
-void Shader::InstructionChain::visit(WriteScratchInstr *instr)
+void Shader::InstructionChain::visit(ScratchIOInstr *instr)
 {
    apply(instr, &last_scratch_instr);
 }
index 6e2e5d8..1eaa878 100644 (file)
@@ -368,7 +368,7 @@ private:
       void visit(LDSAtomicInstr *instr) override {(void) instr;}
       void visit(LDSReadInstr *instr) override {(void) instr;}
 
-      void visit(WriteScratchInstr *instr) override;
+      void visit(ScratchIOInstr *instr) override;
       void visit(GDSInstr *instr) override;
       void visit(RatInstr *instr) override;
 
index df6a9ac..4bb713e 100644 (file)
@@ -518,12 +518,12 @@ TEST_F(TestInstrFromString, test_write_scratch_to_offset)
 {
    add_dest_vec4_from_string("R1.xyzw");
    string init = "WRITE_SCRATCH 20 R1.xyzw AL:4 ALO:16";
-   WriteScratchInstr expect(RegisterVec4(1), 20, 4, 16, 0xf);
+   ScratchIOInstr expect(RegisterVec4(1), 20, 4, 16, 0xf);
    check(init, expect);
 
    add_dest_vec4_from_string("R2.xyzw");
    string init2 = "WRITE_SCRATCH 10 R2.xy_w AL:8 ALO:8";
-   WriteScratchInstr expect2(RegisterVec4(2), 10, 8, 8, 0xb);
+   ScratchIOInstr expect2(RegisterVec4(2), 10, 8, 8, 0xb);
    check(init2, expect2);
 }
 
@@ -532,13 +532,13 @@ TEST_F(TestInstrFromString, test_write_scratch_to_index)
    add_dest_vec4_from_string("R1.xyzw");
    add_dest_from_string("R3.x");
    string init = "WRITE_SCRATCH @R3.x[10] R1.xyzw AL:4 ALO:16";
-   WriteScratchInstr expect(RegisterVec4(1), new Register(3, 0, pin_none), 4, 16, 0xf, 10);
+   ScratchIOInstr expect(RegisterVec4(1), new Register(3, 0, pin_none), 4, 16, 0xf, 10);
    check(init, expect);
 
    add_dest_vec4_from_string("R2.xyzw");
    add_dest_from_string("R4.x");
    string init2 = "WRITE_SCRATCH @R4.x[20] R2.xy__ AL:4 ALO:16";
-   WriteScratchInstr expect2(RegisterVec4(2), new Register(4, 0, pin_none), 4, 16, 0x3, 20);
+   ScratchIOInstr expect2(RegisterVec4(2), new Register(4, 0, pin_none), 4, 16, 0x3, 20);
    check(init2, expect2);