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#include "helpers.h"
25#include "sid.h"
26
27using namespace aco;
28
29static void create_mubuf(Temp desc=Temp(0, s8), unsigned vtx_binding=0)
30{
31   Operand desc_op(desc);
32   desc_op.setFixed(PhysReg(0));
33   bld.mubuf(aco_opcode::buffer_load_dword, Definition(PhysReg(256), v1), desc_op,
34             Operand(PhysReg(256), v1), Operand::zero(), 0, false)
35      .instr->mubuf()
36      .vtx_binding = vtx_binding;
37}
38
39static void create_mubuf_store()
40{
41   bld.mubuf(aco_opcode::buffer_store_dword, Operand(PhysReg(0), s4), Operand(PhysReg(256), v1),
42             Operand(PhysReg(256), v1), Operand::zero(), 0, false);
43}
44
45static void create_mtbuf(Temp desc=Temp(0, s8), unsigned vtx_binding=0)
46{
47   Operand desc_op(desc);
48   desc_op.setFixed(PhysReg(0));
49   bld.mtbuf(aco_opcode::tbuffer_load_format_x, Definition(PhysReg(256), v1), desc_op,
50             Operand(PhysReg(256), v1), Operand::zero(), V_008F0C_BUF_DATA_FORMAT_32,
51             V_008F0C_BUF_NUM_FORMAT_FLOAT, 0, false)
52      .instr->mtbuf()
53      .vtx_binding = vtx_binding;
54}
55
56static void create_flat()
57{
58   bld.flat(aco_opcode::flat_load_dword, Definition(PhysReg(256), v1),
59             Operand(PhysReg(256), v2), Operand(s2));
60}
61
62static void create_global()
63{
64   bld.global(aco_opcode::global_load_dword, Definition(PhysReg(256), v1),
65              Operand(PhysReg(256), v2), Operand(s2));
66}
67
68static void create_mimg(bool nsa, Temp desc=Temp(0, s8))
69{
70   aco_ptr<MIMG_instruction> mimg{create_instruction<MIMG_instruction>(
71      aco_opcode::image_sample, Format::MIMG, 5, 1)};
72   mimg->definitions[0] = Definition(PhysReg(256), v1);
73   mimg->operands[0] = Operand(desc);
74   mimg->operands[0].setFixed(PhysReg(0));
75   mimg->operands[1] = Operand(PhysReg(0), s4);
76   mimg->operands[2] = Operand(v1);
77   for (unsigned i = 0; i < 2; i++)
78      mimg->operands[3 + i] = Operand(PhysReg(256 + (nsa ? i * 2 : i)), v1);
79   mimg->dmask = 0x1;
80   mimg->dim = ac_image_2d;
81
82   bld.insert(std::move(mimg));
83}
84
85static void create_smem()
86{
87   bld.smem(aco_opcode::s_load_dword, Definition(PhysReg(0), s1), Operand(PhysReg(0), s2),
88            Operand::zero());
89}
90
91static void create_smem_buffer(Temp desc=Temp(0, s4))
92{
93   Operand desc_op(desc);
94   desc_op.setFixed(PhysReg(0));
95   bld.smem(aco_opcode::s_buffer_load_dword, Definition(PhysReg(0), s1), desc_op, Operand::zero());
96}
97
98BEGIN_TEST(form_hard_clauses.type_restrictions)
99   if (!setup_cs(NULL, GFX10))
100      return;
101
102   //>> p_unit_test 0
103   //! s_clause imm:1
104   //; search_re('image_sample')
105   //; search_re('image_sample')
106   bld.pseudo(aco_opcode::p_unit_test, Operand::zero());
107   create_mimg(false);
108   create_mimg(false);
109
110   //>> p_unit_test 1
111   //! s_clause imm:1
112   //; search_re('buffer_load_dword')
113   //; search_re('buffer_load_dword')
114   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u));
115   create_mubuf();
116   create_mubuf();
117
118   //>> p_unit_test 2
119   //! s_clause imm:1
120   //; search_re('global_load_dword')
121   //; search_re('global_load_dword')
122   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u));
123   create_global();
124   create_global();
125
126   //>> p_unit_test 3
127   //! s_clause imm:1
128   //; search_re('flat_load_dword')
129   //; search_re('flat_load_dword')
130   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u));
131   create_flat();
132   create_flat();
133
134   //>> p_unit_test 4
135   //! s_clause imm:1
136   //; search_re('s_load_dword')
137   //; search_re('s_load_dword')
138   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(4u));
139   create_smem();
140   create_smem();
141
142   //>> p_unit_test 5
143   //; search_re('buffer_load_dword')
144   //; search_re('flat_load_dword')
145   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(5u));
146   create_mubuf();
147   create_flat();
148
149   //>> p_unit_test 6
150   //; search_re('buffer_load_dword')
151   //; search_re('s_load_dword')
152   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(6u));
153   create_mubuf();
154   create_smem();
155
156   //>> p_unit_test 7
157   //; search_re('flat_load_dword')
158   //; search_re('s_load_dword')
159   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(7u));
160   create_flat();
161   create_smem();
162
163   finish_form_hard_clause_test();
164END_TEST
165
166BEGIN_TEST(form_hard_clauses.size)
167   if (!setup_cs(NULL, GFX10))
168      return;
169
170   //>> p_unit_test 0
171   //; search_re('s_load_dword')
172   bld.pseudo(aco_opcode::p_unit_test, Operand::zero());
173   create_smem();
174
175   //>> p_unit_test 1
176   //! s_clause imm:63
177   //; for i in range(64):
178   //;    search_re('s_load_dword')
179   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u));
180   for (unsigned i = 0; i < 64; i++)
181      create_smem();
182
183   //>> p_unit_test 2
184   //! s_clause imm:63
185   //; for i in range(65):
186   //;    search_re('s_load_dword')
187   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u));
188   for (unsigned i = 0; i < 65; i++)
189      create_smem();
190
191   //>> p_unit_test 3
192   //! s_clause imm:63
193   //; for i in range(64):
194   //;    search_re('s_load_dword')
195   //! s_clause imm:1
196   //; search_re('s_load_dword')
197   //; search_re('s_load_dword')
198   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u));
199   for (unsigned i = 0; i < 66; i++)
200      create_smem();
201
202   finish_form_hard_clause_test();
203END_TEST
204
205BEGIN_TEST(form_hard_clauses.nsa)
206   for (unsigned i = GFX10; i <= GFX10_3; i++) {
207      if (!setup_cs(NULL, (amd_gfx_level)i))
208         continue;
209
210      //>> p_unit_test 0
211      //! s_clause imm:1
212      //; search_re('image_sample .* %0:v\[0\], %0:v\[1\]')
213      //; search_re('image_sample .* %0:v\[0\], %0:v\[1\]')
214      bld.pseudo(aco_opcode::p_unit_test, Operand::zero());
215      create_mimg(false);
216      create_mimg(false);
217
218      //>> p_unit_test 1
219      //~gfx10_3! s_clause imm:1
220      //; search_re('image_sample .* %0:v\[0\], %0:v\[1\]')
221      //; search_re('image_sample .* %0:v\[0\], %0:v\[2\]')
222      bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u));
223      create_mimg(false);
224      create_mimg(true);
225
226      //>> p_unit_test 2
227      //~gfx10_3! s_clause imm:1
228      //; search_re('image_sample .* %0:v\[0\], %0:v\[2\]')
229      //; search_re('image_sample .* %0:v\[0\], %0:v\[2\]')
230      bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u));
231      create_mimg(true);
232      create_mimg(true);
233
234      finish_form_hard_clause_test();
235   }
236END_TEST
237
238BEGIN_TEST(form_hard_clauses.heuristic)
239   if (!setup_cs(NULL, GFX10))
240      return;
241
242   Temp img_desc0 = bld.tmp(s8);
243   Temp img_desc1 = bld.tmp(s8);
244   Temp buf_desc0 = bld.tmp(s4);
245   Temp buf_desc1 = bld.tmp(s4);
246
247   /* Don't form clause with different descriptors */
248   //>> p_unit_test 0
249   //! s_clause imm:1
250   //; search_re('image_sample')
251   //; search_re('image_sample')
252   bld.pseudo(aco_opcode::p_unit_test, Operand::zero());
253   create_mimg(false, img_desc0);
254   create_mimg(false, img_desc0);
255
256   //>> p_unit_test 1
257   //; search_re('image_sample')
258   //; search_re('image_sample')
259   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u));
260   create_mimg(false, img_desc0);
261   create_mimg(false, img_desc1);
262
263   //>> p_unit_test 2
264   //! s_clause imm:1
265   //; search_re('buffer_load_dword')
266   //; search_re('buffer_load_dword')
267   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u));
268   create_mubuf(buf_desc0);
269   create_mubuf(buf_desc0);
270
271   //>> p_unit_test 3
272   //; search_re('buffer_load_dword')
273   //; search_re('buffer_load_dword')
274   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u));
275   create_mubuf(buf_desc0);
276   create_mubuf(buf_desc1);
277
278   //>> p_unit_test 4
279   //! s_clause imm:1
280   //; search_re('s_buffer_load_dword')
281   //; search_re('s_buffer_load_dword')
282   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(4u));
283   create_smem_buffer(buf_desc0);
284   create_smem_buffer(buf_desc0);
285
286   //>> p_unit_test 5
287   //; search_re('s_buffer_load_dword')
288   //; search_re('s_buffer_load_dword')
289   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(5u));
290   create_smem_buffer(buf_desc0);
291   create_smem_buffer(buf_desc1);
292
293   //>> p_unit_test 6
294   //; search_re('s_buffer_load_dword')
295   //; search_re('s_load_dword')
296   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(6u));
297   create_smem_buffer(buf_desc0);
298   create_smem();
299
300   /* Only form clause between MUBUF and MTBUF if they load from the same binding. Ignore descriptor
301    * if they're te same binding.
302    */
303   //>> p_unit_test 7
304   //; search_re('buffer_load_dword')
305   //; search_re('tbuffer_load_format_x')
306   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(7u));
307   create_mubuf(buf_desc0);
308   create_mtbuf(buf_desc0);
309
310   //>> p_unit_test 8
311   //! s_clause imm:1
312   //; search_re('buffer_load_dword')
313   //; search_re('tbuffer_load_format_x')
314   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(8u));
315   create_mubuf(buf_desc0, 1);
316   create_mtbuf(buf_desc0, 1);
317
318   //>> p_unit_test 9
319   //! s_clause imm:1
320   //; search_re('buffer_load_dword')
321   //; search_re('tbuffer_load_format_x')
322   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(9u));
323   create_mubuf(buf_desc0, 1);
324   create_mtbuf(buf_desc1, 1);
325
326   finish_form_hard_clause_test();
327END_TEST
328
329BEGIN_TEST(form_hard_clauses.stores)
330   if (!setup_cs(NULL, GFX10))
331      return;
332
333   //>> p_unit_test 0
334   //; search_re('buffer_store_dword')
335   //; search_re('buffer_store_dword')
336   bld.pseudo(aco_opcode::p_unit_test, Operand::zero());
337   create_mubuf_store();
338   create_mubuf_store();
339
340   //>> p_unit_test 1
341   //! s_clause imm:1
342   //; search_re('buffer_load_dword')
343   //; search_re('buffer_load_dword')
344   //; search_re('buffer_store_dword')
345   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u));
346   create_mubuf();
347   create_mubuf();
348   create_mubuf_store();
349
350   //>> p_unit_test 2
351   //; search_re('buffer_store_dword')
352   //! s_clause imm:1
353   //; search_re('buffer_load_dword')
354   //; search_re('buffer_load_dword')
355   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u));
356   create_mubuf_store();
357   create_mubuf();
358   create_mubuf();
359
360   /* Unclear whether this is the best behaviour */
361   //>> p_unit_test 3
362   //; search_re('buffer_load_dword')
363   //; search_re('buffer_store_dword')
364   //; search_re('buffer_load_dword')
365   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u));
366   create_mubuf();
367   create_mubuf_store();
368   create_mubuf();
369
370   /* Unimportant pass limitations */
371   //>> p_unit_test 4
372   //; search_re('buffer_store_dword')
373   //! s_clause imm:62
374   //; for i in range(63):
375   //;    search_re('buffer_load_dword')
376   //; search_re('buffer_load_dword')
377   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(4u));
378   create_mubuf_store();
379   for (unsigned i = 0; i < 64; i++)
380      create_mubuf();
381
382   //>> p_unit_test 5
383   //! s_clause imm:63
384   //; for i in range(64):
385   //;    search_re('buffer_load_dword')
386   //; search_re('buffer_store_dword')
387   bld.pseudo(aco_opcode::p_unit_test, Operand::c32(5u));
388   for (unsigned i = 0; i < 64; i++)
389      create_mubuf();
390   create_mubuf_store();
391
392   finish_form_hard_clause_test();
393END_TEST
394