• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2020 Valve Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #include "aco_builder.h"
26 #include "aco_ir.h"
27 
28 #include <vector>
29 
30 namespace aco {
31 namespace {
32 
33 /* there can also be LDS and VALU clauses, but I don't see how those are interesting */
34 enum clause_type {
35    clause_vmem,
36    clause_flat,
37    clause_smem,
38    clause_other,
39 };
40 
41 void
emit_clause(Builder & bld,unsigned num_instrs,aco_ptr<Instruction> * instrs)42 emit_clause(Builder& bld, unsigned num_instrs, aco_ptr<Instruction>* instrs)
43 {
44    unsigned start = 0;
45 
46    /* skip any stores at the start */
47    for (; (start < num_instrs) && instrs[start]->definitions.empty(); start++)
48       bld.insert(std::move(instrs[start]));
49 
50    unsigned end = start;
51    for (; (end < num_instrs) && !instrs[end]->definitions.empty(); end++)
52       ;
53    unsigned clause_size = end - start;
54 
55    if (clause_size > 1)
56       bld.sopp(aco_opcode::s_clause, -1, clause_size - 1);
57 
58    for (unsigned i = start; i < num_instrs; i++)
59       bld.insert(std::move(instrs[i]));
60 }
61 
62 } /* end namespace */
63 
64 void
form_hard_clauses(Program * program)65 form_hard_clauses(Program* program)
66 {
67    for (Block& block : program->blocks) {
68       unsigned num_instrs = 0;
69       aco_ptr<Instruction> current_instrs[64];
70       clause_type current_type = clause_other;
71 
72       std::vector<aco_ptr<Instruction>> new_instructions;
73       new_instructions.reserve(block.instructions.size());
74       Builder bld(program, &new_instructions);
75 
76       for (unsigned i = 0; i < block.instructions.size(); i++) {
77          aco_ptr<Instruction>& instr = block.instructions[i];
78 
79          clause_type type = clause_other;
80          if (instr->isVMEM() && !instr->operands.empty()) {
81             if (program->gfx_level == GFX10 && instr->isMIMG() &&
82                 get_mimg_nsa_dwords(instr.get()) > 0)
83                type = clause_other;
84             else
85                type = clause_vmem;
86          } else if (instr->isScratch() || instr->isGlobal()) {
87             type = clause_vmem;
88          } else if (instr->isFlat()) {
89             type = clause_flat;
90          } else if (instr->isSMEM() && !instr->operands.empty()) {
91             type = clause_smem;
92          }
93 
94          if (type != current_type || num_instrs == 64 ||
95              (num_instrs && !should_form_clause(current_instrs[0].get(), instr.get()))) {
96             emit_clause(bld, num_instrs, current_instrs);
97             num_instrs = 0;
98             current_type = type;
99          }
100 
101          if (type == clause_other) {
102             bld.insert(std::move(instr));
103             continue;
104          }
105 
106          current_instrs[num_instrs++] = std::move(instr);
107       }
108 
109       emit_clause(bld, num_instrs, current_instrs);
110 
111       block.instructions = std::move(new_instructions);
112    }
113 }
114 } // namespace aco
115