~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/gallium/drivers/r600/sfn/sfn_split_address_loads.cpp

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mesa-c++  -*-
 
2
 *
 
3
 * Copyright (c) 2022 Collabora LTD
 
4
 *
 
5
 * Author: Gert Wollny <gert.wollny@collabora.com>
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 
11
 * license, and/or sell copies of the Software, and to permit persons to whom
 
12
 * the Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice (including the next
 
15
 * paragraph) shall be included in all copies or substantial portions of the
 
16
 * Software.
 
17
 *
 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 
21
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 
22
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
23
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 
24
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 */
 
26
 
 
27
#include "sfn_split_address_loads.h"
 
28
#include "r600_isa.h"
 
29
#include "sfn_alu_defines.h"
 
30
#include "sfn_defines.h"
 
31
#include "sfn_instr_alugroup.h"
 
32
#include "sfn_instr_fetch.h"
 
33
#include "sfn_instr_mem.h"
 
34
#include "sfn_instr_tex.h"
 
35
#include "sfn_instr_export.h"
 
36
 
 
37
namespace r600 {
 
38
 
 
39
 
 
40
class AddressSplitVisitor : public InstrVisitor {
 
41
public: 
 
42
   AddressSplitVisitor(Shader& sh); 
 
43
   
 
44
private:    
 
45
   void visit(AluInstr *instr) override;
 
46
   void visit(AluGroup *instr) override;
 
47
   void visit(TexInstr *instr) override;
 
48
   void visit(ExportInstr *instr) override;
 
49
   void visit(FetchInstr *instr) override;
 
50
   void visit(Block *instr) override;
 
51
   void visit(ControlFlowInstr *instr) override;
 
52
   void visit(IfInstr *instr) override;
 
53
   void visit(ScratchIOInstr *instr) override;
 
54
   void visit(StreamOutInstr *instr) override;
 
55
   void visit(MemRingOutInstr *instr) override;
 
56
   void visit(EmitVertexInstr *instr) override;
 
57
   void visit(GDSInstr *instr) override;
 
58
   void visit(WriteTFInstr *instr) override;
 
59
   void visit(LDSAtomicInstr *instr) override;
 
60
   void visit(LDSReadInstr *instr) override;
 
61
   void visit(RatInstr *instr) override;
 
62
   
 
63
   void load_ar(Instr *instr, PRegister addr);
 
64
   auto load_index_register(Instr *instr, PRegister index) -> int;
 
65
   auto load_index_register_eg(Instr *instr, PRegister index) -> int;
 
66
   auto load_index_register_ca(PRegister index) -> int;
 
67
   auto reuse_loaded_idx(PRegister index) -> int;
 
68
   auto pick_idx() -> int ;
 
69
 
 
70
   ValueFactory& m_vf;
 
71
   r600_chip_class m_chip_class;
 
72
   
 
73
   Block::iterator m_block_iterator; 
 
74
   Block *m_current_block{nullptr}; 
 
75
   PRegister m_current_addr{nullptr};
 
76
   PRegister m_current_idx[2] {nullptr, nullptr};
 
77
   PRegister m_current_idx_src[2] {nullptr, nullptr};
 
78
 
 
79
 
 
80
   std::list<Instr *> m_last_ar_use;
 
81
   AluInstr *m_last_ar_load{nullptr};
 
82
 
 
83
   unsigned m_linear_index{0};
 
84
   unsigned m_last_idx_load_index[2] {0,0};
 
85
   AluInstr *m_last_idx_load[2] {nullptr, nullptr};
 
86
   std::list<Instr *> m_last_idx_use[2];
 
87
   std::list<Instr *> m_prev_non_alu;
 
88
 
 
89
};
 
90
 
 
91
 
 
92
bool split_address_loads(Shader& sh)
 
93
{
 
94
   AddressSplitVisitor visitor(sh); 
 
95
   for (auto block : sh.func()) {
 
96
      block->accept(visitor); 
 
97
   }
 
98
   return true;
 
99
}
 
100
 
 
101
AddressSplitVisitor::AddressSplitVisitor(Shader& sh):
 
102
   m_vf(sh.value_factory()), 
 
103
   m_chip_class(sh.chip_class())
 
104
{   
 
105
}   
 
106
 
 
107
class CollectDeps : public ConstRegisterVisitor {
 
108
public:
 
109
   void visit(const Register& r) override
 
110
   {
 
111
      for (auto p : r.parents())
 
112
         add_dep(p);
 
113
   }
 
114
   void visit(const LocalArray& value) override {(void)value; unreachable("Array is not a value");}
 
115
   void visit(const LocalArrayValue& r) override
 
116
   {
 
117
      auto& a = r.array();
 
118
      for (auto reg : a) {
 
119
         if (!instr->dest() || !reg->equal_to(*instr->dest())) {
 
120
            for (auto p : reg->parents()) {
 
121
               if ((instr->block_id() == p->block_id()) &&
 
122
                   (instr->index() > p->index()))
 
123
                  add_dep(p);
 
124
            }
 
125
         }
 
126
      }
 
127
   }
 
128
   void visit(const UniformValue& value) override {(void)value;}
 
129
   void visit(const LiteralConstant& value) override {(void)value;}
 
130
   void visit(const InlineConstant& value) override {(void)value;}
 
131
 
 
132
   void add_dep(Instr *p) {
 
133
 
 
134
      auto alu = p->as_alu();
 
135
      if (!alu || alu_level > 1) {
 
136
         instr->add_required_instr(p);
 
137
      } else  {
 
138
         ++alu_level;
 
139
         for (auto& s : alu->sources()) {
 
140
            if (!alu->dest() || !alu->dest()->equal_to(*s))
 
141
               s->accept(*this);
 
142
         }
 
143
         --alu_level;
 
144
      }
 
145
   }
 
146
   int alu_level{0};
 
147
 
 
148
   AluInstr *instr;
 
149
};
 
150
 
 
151
 
 
152
void AddressSplitVisitor::visit(AluInstr *instr)
 
153
{
 
154
   auto [addr, is_for_dest, index] = instr->indirect_addr();
 
155
   
 
156
   if (addr) {
 
157
      assert(!index);
 
158
 
 
159
      if (!m_current_addr || !m_current_addr->equal_to(*addr))
 
160
         load_ar(instr, addr);
 
161
 
 
162
      // Do this with a visitor to catch also local array values
 
163
      CollectDeps collector;
 
164
      collector.instr = m_last_ar_load;
 
165
      for (auto& s : instr->sources()) {
 
166
         s->accept(collector);
 
167
      }
 
168
 
 
169
      instr->update_indirect_addr(m_vf.addr());
 
170
      addr->del_use(instr);
 
171
      m_last_ar_load->inc_ar_uses();
 
172
      m_last_ar_use.push_back(instr);
 
173
   }
 
174
 
 
175
   if (index)
 
176
      load_index_register(instr, index);
 
177
}
 
178
 
 
179
auto AddressSplitVisitor::load_index_register(Instr *instr, PRegister index) -> int
 
180
{
 
181
   int idx_id = m_chip_class < ISA_CC_CAYMAN ?
 
182
                   load_index_register_eg(instr, index):
 
183
                   load_index_register_ca(index);
 
184
 
 
185
   m_last_idx_use[idx_id].push_back(instr);
 
186
 
 
187
   index->del_use(instr);
 
188
   instr->update_indirect_addr(m_current_idx[idx_id]);
 
189
   m_last_idx_load_index[idx_id] = (instr->block_id() << 16) | instr->index();
 
190
   return idx_id == 0 ? bim_zero : bim_one;
 
191
}
 
192
 
 
193
auto AddressSplitVisitor::load_index_register_eg(Instr *instr,
 
194
                                                 PRegister index)  -> int
 
195
{
 
196
   int idx_id = reuse_loaded_idx(index);
 
197
   if (idx_id < 0) {
 
198
      load_ar(instr, index);
 
199
 
 
200
      idx_id = pick_idx();
 
201
      auto idx = m_vf.idx_reg(idx_id);
 
202
 
 
203
      const EAluOp idx_op[2] = {op1_set_cf_idx0, op1_set_cf_idx1};
 
204
 
 
205
      m_last_idx_load[idx_id] = new AluInstr(idx_op[idx_id], idx, m_vf.addr(), {});
 
206
      m_current_block->insert(m_block_iterator, m_last_idx_load[idx_id]);
 
207
      for (auto&& i : m_last_idx_use[idx_id])
 
208
         m_last_idx_load[idx_id]->add_required_instr(i);
 
209
      m_last_idx_use[idx_id].clear();
 
210
 
 
211
      m_last_ar_load->inc_ar_uses();
 
212
      m_last_ar_use.push_back(m_last_idx_load[idx_id]);
 
213
      m_current_idx[idx_id] = idx;
 
214
      m_current_idx_src[idx_id] = index;
 
215
 
 
216
   }
 
217
   return idx_id;
 
218
}
 
219
 
 
220
auto AddressSplitVisitor::load_index_register_ca(PRegister index)  -> int
 
221
{
 
222
   int idx_id = reuse_loaded_idx(index);
 
223
   if (idx_id < 0) {
 
224
      idx_id = pick_idx();
 
225
      auto idx = m_vf.idx_reg(idx_id);
 
226
      m_last_idx_load[idx_id] = new AluInstr(op1_mova_int, idx, index, {});
 
227
 
 
228
      m_current_block->insert(m_block_iterator, m_last_idx_load[idx_id]);
 
229
      for (auto&& i : m_last_idx_use[idx_id])
 
230
         m_last_idx_load[idx_id]->add_required_instr(i);
 
231
      m_last_idx_use[idx_id].clear();
 
232
      m_current_idx[idx_id] = idx;
 
233
      m_current_idx_src[idx_id] = index;
 
234
 
 
235
   }
 
236
   return idx_id;
 
237
}
 
238
 
 
239
auto AddressSplitVisitor::reuse_loaded_idx(PRegister index) -> int
 
240
{
 
241
   for (int i = 0; i < 2; ++i) {
 
242
      if (m_current_idx_src[i] && m_current_idx_src[i]->equal_to(*index)) {
 
243
         return i;
 
244
      }
 
245
   }
 
246
   return -1;
 
247
}
 
248
 
 
249
auto AddressSplitVisitor::pick_idx() -> int
 
250
{
 
251
   int idx_id = -1;
 
252
   if (!m_current_idx[0]) {
 
253
      idx_id = 0;
 
254
   } else if (!m_current_idx[1]) {
 
255
      idx_id = 1;
 
256
   } else {
 
257
      idx_id = m_last_idx_load_index[0] < m_last_idx_load_index[1] ? 0 : 1;
 
258
   }
 
259
   return idx_id;
 
260
}
 
261
 
 
262
 
 
263
void AddressSplitVisitor::load_ar(Instr *instr, PRegister addr)
 
264
{
 
265
   auto ar = m_vf.addr();
 
266
 
 
267
   m_last_ar_load = new AluInstr(op1_mova_int, ar, addr, {});
 
268
   m_current_block->insert(m_block_iterator, m_last_ar_load);
 
269
   ar->add_use(instr);
 
270
   m_current_addr = addr;
 
271
   for (auto& i : m_last_ar_use) {
 
272
      m_last_ar_load->add_required_instr(i);
 
273
   }
 
274
   for (auto na: m_prev_non_alu) {
 
275
      m_last_ar_load->add_required_instr(na);
 
276
   }
 
277
   m_last_ar_use.clear();
 
278
}
 
279
 
 
280
 
 
281
void AddressSplitVisitor::visit(AluGroup *instr)
 
282
{
 
283
   for (auto& i : *instr)
 
284
      if (i)
 
285
         this->visit(i);
 
286
}
 
287
 
 
288
void AddressSplitVisitor::visit(TexInstr *instr)
 
289
{
 
290
   if (instr->resource_offset())
 
291
      load_index_register(instr, instr->resource_offset());
 
292
   m_prev_non_alu.push_back(instr);
 
293
   m_current_addr = nullptr;
 
294
}
 
295
void AddressSplitVisitor::visit(ExportInstr *instr)
 
296
{
 
297
   (void)instr;
 
298
   m_current_addr = nullptr;
 
299
}
 
300
 
 
301
void AddressSplitVisitor::visit(FetchInstr *instr)
 
302
{
 
303
   if (instr->resource_offset())
 
304
      load_index_register(instr, instr->resource_offset());
 
305
   m_prev_non_alu.push_back(instr);
 
306
   m_current_addr = nullptr;
 
307
}
 
308
 
 
309
void AddressSplitVisitor::visit(Block *instr)
 
310
{
 
311
   m_current_block = instr;
 
312
   m_block_iterator = instr->begin(); 
 
313
   m_last_ar_load = nullptr;
 
314
   m_current_addr = nullptr;
 
315
   m_last_ar_use.clear();
 
316
   auto e = instr->end(); 
 
317
   while (m_block_iterator != e) {
 
318
      (*m_block_iterator)->accept(*this); 
 
319
      ++m_block_iterator; 
 
320
   }
 
321
   
 
322
   // renumber instructions 
 
323
   int new_index = 0;
 
324
   for (auto&& i : *instr)
 
325
      i->set_blockid(m_current_block->id(), new_index++); 
 
326
}
 
327
void AddressSplitVisitor::visit(ControlFlowInstr *instr)
 
328
{
 
329
    (void)instr;
 
330
   m_current_addr = nullptr;
 
331
}
 
332
void AddressSplitVisitor::visit(IfInstr *instr)
 
333
{
 
334
   visit(instr->predicate());
 
335
   m_current_addr = nullptr;
 
336
}
 
337
void AddressSplitVisitor::visit(ScratchIOInstr *instr)
 
338
{
 
339
    m_prev_non_alu.push_back(instr);
 
340
    m_current_addr = nullptr;
 
341
    (void)instr;
 
342
}
 
343
void AddressSplitVisitor::visit(StreamOutInstr *instr)
 
344
{
 
345
    m_prev_non_alu.push_back(instr);
 
346
    m_current_addr = nullptr;
 
347
    (void)instr;
 
348
}
 
349
void AddressSplitVisitor::visit(MemRingOutInstr *instr)
 
350
{
 
351
    m_prev_non_alu.push_back(instr);
 
352
    m_current_addr = nullptr;
 
353
    (void)instr;
 
354
}
 
355
void AddressSplitVisitor::visit(EmitVertexInstr *instr)
 
356
{
 
357
    m_prev_non_alu.push_back(instr);
 
358
    m_current_addr = nullptr;
 
359
    (void)instr;
 
360
}
 
361
void AddressSplitVisitor::visit(GDSInstr *instr)
 
362
{
 
363
   if (instr->resource_offset())
 
364
      load_index_register(instr, instr->resource_offset());
 
365
   m_prev_non_alu.push_back(instr);
 
366
   m_current_addr = nullptr;
 
367
}
 
368
void AddressSplitVisitor::visit(WriteTFInstr *instr)
 
369
{
 
370
    m_prev_non_alu.push_back(instr);
 
371
    m_current_addr = nullptr;
 
372
    (void)instr;
 
373
}
 
374
 
 
375
void AddressSplitVisitor::visit(LDSAtomicInstr *instr)
 
376
{
 
377
   (void)instr;
 
378
}
 
379
 
 
380
void AddressSplitVisitor::visit(LDSReadInstr *instr)
 
381
{
 
382
   (void)instr;
 
383
}
 
384
void AddressSplitVisitor::visit(RatInstr *instr)
 
385
{
 
386
   if (instr->resource_offset())
 
387
      load_index_register(instr, instr->resource_offset());
 
388
   m_prev_non_alu.push_back(instr);
 
389
   m_current_addr = nullptr;
 
390
}
 
391
 
 
392
}