aco: explicitly mark end blocks for exports
authorRhys Perry <pendingchaos02@gmail.com>
Fri, 15 Nov 2019 11:43:19 +0000 (11:43 +0000)
committerMarge Bot <eric+marge@anholt.net>
Fri, 24 Jan 2020 13:35:07 +0000 (13:35 +0000)
For GS copy shaders, whether we want to do exports is conditional. By
explicitly marking the end blocks, we can mark an IF's then branch as an
export block and ensure that's where the assembler inserts null exports.

v6: only fixup exports in the end block, like before
v8: simplify some code

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_assembler.cpp
src/amd/compiler/aco_instruction_selection.cpp
src/amd/compiler/aco_ir.h

index c7088a498b5df2ded33a2fccbca2b2fa27d131fe..94c41173d6eafacb7b12e2a78c3ce3c5e73c9f0d 100644 (file)
@@ -595,14 +595,14 @@ void emit_block(asm_context& ctx, std::vector<uint32_t>& out, Block& block)
 
 void fix_exports(asm_context& ctx, std::vector<uint32_t>& out, Program* program)
 {
-   for (int idx = program->blocks.size() - 1; idx >= 0; idx--) {
-      Block& block = program->blocks[idx];
+   for (Block& block : program->blocks) {
+      if (!(block.kind & block_kind_export_end))
+         continue;
       std::vector<aco_ptr<Instruction>>::reverse_iterator it = block.instructions.rbegin();
-      bool endBlock = false;
       bool exported = false;
       while ( it != block.instructions.rend())
       {
-         if ((*it)->format == Format::EXP && endBlock) {
+         if ((*it)->format == Format::EXP) {
             Export_instruction* exp = static_cast<Export_instruction*>((*it).get());
             if (program->stage & hw_vs) {
                if (exp->dest >= V_008DFC_SQ_EXP_POS && exp->dest <= (V_008DFC_SQ_EXP_POS + 3)) {
@@ -618,14 +618,9 @@ void fix_exports(asm_context& ctx, std::vector<uint32_t>& out, Program* program)
             }
          } else if ((*it)->definitions.size() && (*it)->definitions[0].physReg() == exec)
             break;
-         else if ((*it)->opcode == aco_opcode::s_endpgm) {
-            if (endBlock)
-               break;
-            endBlock = true;
-         }
          ++it;
       }
-      if (!endBlock || exported)
+      if (exported)
          continue;
       /* we didn't find an Export instruction and have to insert a null export */
       aco_ptr<Export_instruction> exp{create_instruction<Export_instruction>(aco_opcode::exp, Format::EXP, 4, 0)};
@@ -639,7 +634,7 @@ void fix_exports(asm_context& ctx, std::vector<uint32_t>& out, Program* program)
          exp->dest = 9; /* NULL */
       else
          exp->dest = V_008DFC_SQ_EXP_POS;
-      /* insert the null export 1 instruction before endpgm */
+      /* insert the null export 1 instruction before branch/endpgm */
       block.instructions.insert(block.instructions.end() - 1, std::move(exp));
    }
 }
index c3e9cf9f913cacd591dac6626fa258310604bad5..4d464cc935e8ab570578c5e2a23a873c91594674 100644 (file)
@@ -8874,7 +8874,7 @@ void select_program(Program *program,
    program->config->float_mode = program->blocks[0].fp_mode.val;
 
    append_logical_end(ctx.block);
-   ctx.block->kind |= block_kind_uniform;
+   ctx.block->kind |= block_kind_uniform | block_kind_export_end;
    Builder bld(ctx.program, ctx.block);
    if (ctx.program->wb_smem_l1_on_end)
       bld.smem(aco_opcode::s_dcache_wb, false);
index 24d1acf2b79cecc846da53e3279d2f2ac5690421..d3ebecc081ecba43b98a64f9dbf70a6ea1917747 100644 (file)
@@ -1002,6 +1002,7 @@ enum block_kind {
    block_kind_uses_discard_if = 1 << 12,
    block_kind_needs_lowering = 1 << 13,
    block_kind_uses_demote = 1 << 14,
+   block_kind_export_end = 1 << 15,
 };