1 /*
2 * Copyright © 2019 Intel 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 <gtest/gtest.h>
25 #include "brw_fs.h"
26 #include "brw_fs_builder.h"
27 #include "brw_cfg.h"
28
29 using namespace brw;
30
31 class scoreboard_test : public ::testing::Test {
32 protected:
33 scoreboard_test();
34 ~scoreboard_test() override;
35
36 struct brw_compiler *compiler;
37 struct brw_compile_params params;
38 struct intel_device_info *devinfo;
39 void *ctx;
40 struct brw_wm_prog_data *prog_data;
41 struct gl_shader_program *shader_prog;
42 fs_visitor *v;
43 fs_builder bld;
44 };
45
scoreboard_test()46 scoreboard_test::scoreboard_test()
47 : bld(NULL, 0)
48 {
49 ctx = ralloc_context(NULL);
50 compiler = rzalloc(ctx, struct brw_compiler);
51 devinfo = rzalloc(ctx, struct intel_device_info);
52 devinfo->ver = 12;
53 devinfo->verx10 = devinfo->ver * 10;
54
55 compiler->devinfo = devinfo;
56 brw_init_isa_info(&compiler->isa, devinfo);
57
58 params = {};
59 params.mem_ctx = ctx;
60
61 prog_data = ralloc(ctx, struct brw_wm_prog_data);
62 nir_shader *shader =
63 nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
64
65 v = new fs_visitor(compiler, ¶ms, NULL, &prog_data->base, shader, 8,
66 false, false);
67
68 bld = fs_builder(v).at_end();
69 }
70
~scoreboard_test()71 scoreboard_test::~scoreboard_test()
72 {
73 delete v;
74 v = NULL;
75
76 ralloc_free(ctx);
77 ctx = NULL;
78 }
79
80 static fs_inst *
instruction(bblock_t * block,int num)81 instruction(bblock_t *block, int num)
82 {
83 fs_inst *inst = (fs_inst *)block->start();
84 for (int i = 0; i < num; i++) {
85 inst = (fs_inst *)inst->next;
86 }
87 return inst;
88 }
89
90 static void
lower_scoreboard(fs_visitor * v)91 lower_scoreboard(fs_visitor *v)
92 {
93 const bool print = getenv("TEST_DEBUG");
94
95 if (print) {
96 fprintf(stderr, "= Before =\n");
97 v->cfg->dump();
98 }
99
100 brw_fs_lower_scoreboard(*v);
101
102 if (print) {
103 fprintf(stderr, "\n= After =\n");
104 v->cfg->dump();
105 }
106 }
107
108 fs_inst *
emit_SEND(const fs_builder & bld,const brw_reg & dst,const brw_reg & desc,const brw_reg & payload)109 emit_SEND(const fs_builder &bld, const brw_reg &dst,
110 const brw_reg &desc, const brw_reg &payload)
111 {
112 fs_inst *inst = bld.emit(SHADER_OPCODE_SEND, dst, desc, desc, payload);
113 inst->mlen = 1;
114 return inst;
115 }
116
117 static tgl_swsb
tgl_swsb_testcase(unsigned regdist,unsigned sbid,enum tgl_sbid_mode mode)118 tgl_swsb_testcase(unsigned regdist, unsigned sbid, enum tgl_sbid_mode mode)
119 {
120 tgl_swsb swsb = tgl_swsb_sbid(mode, sbid);
121 swsb.regdist = regdist;
122 return swsb;
123 }
124
operator ==(const tgl_swsb & a,const tgl_swsb & b)125 bool operator ==(const tgl_swsb &a, const tgl_swsb &b)
126 {
127 return a.mode == b.mode &&
128 a.regdist == b.regdist &&
129 (a.mode == TGL_SBID_NULL || a.sbid == b.sbid);
130 }
131
operator <<(std::ostream & os,const tgl_swsb & swsb)132 std::ostream &operator<<(std::ostream &os, const tgl_swsb &swsb) {
133 char *buf;
134 size_t len;
135 FILE *f = open_memstream(&buf, &len);
136
137 /* Because we don't have a devinfo to pass here, for TGL we'll see
138 * F@1 annotations instead of @1 since the float pipe is the only one
139 * used there.
140 */
141 brw_print_swsb(f, NULL, swsb);
142 fflush(f);
143 fclose(f);
144
145 os << buf;
146 free(buf);
147
148 return os;
149 }
150
TEST_F(scoreboard_test,RAW_inorder_inorder)151 TEST_F(scoreboard_test, RAW_inorder_inorder)
152 {
153 brw_reg g[16];
154 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
155 g[i] = bld.vgrf(BRW_TYPE_D);
156
157 brw_reg x = bld.vgrf(BRW_TYPE_D);
158 brw_reg y = bld.vgrf(BRW_TYPE_D);
159 bld.ADD( x, g[1], g[2]);
160 bld.MUL( y, g[3], g[4]);
161 bld.AND(g[5], x, y);
162
163 brw_calculate_cfg(*v);
164 bblock_t *block0 = v->cfg->blocks[0];
165 ASSERT_EQ(0, block0->start_ip);
166 ASSERT_EQ(2, block0->end_ip);
167
168 lower_scoreboard(v);
169 ASSERT_EQ(0, block0->start_ip);
170 ASSERT_EQ(2, block0->end_ip);
171
172 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
173 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
174 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_regdist(1));
175 }
176
TEST_F(scoreboard_test,RAW_inorder_outoforder)177 TEST_F(scoreboard_test, RAW_inorder_outoforder)
178 {
179 brw_reg g[16];
180 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
181 g[i] = bld.vgrf(BRW_TYPE_D);
182
183 brw_reg x = bld.vgrf(BRW_TYPE_D);
184 bld.ADD( x, g[1], g[2]);
185 bld.MUL( g[3], g[4], g[5]);
186 emit_SEND(bld, g[6], g[7], x);
187
188 brw_calculate_cfg(*v);
189 bblock_t *block0 = v->cfg->blocks[0];
190 ASSERT_EQ(0, block0->start_ip);
191 ASSERT_EQ(2, block0->end_ip);
192
193 lower_scoreboard(v);
194 ASSERT_EQ(0, block0->start_ip);
195 ASSERT_EQ(2, block0->end_ip);
196
197 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
198 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
199 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_testcase(2, 0, TGL_SBID_SET));
200 }
201
TEST_F(scoreboard_test,RAW_outoforder_inorder)202 TEST_F(scoreboard_test, RAW_outoforder_inorder)
203 {
204 brw_reg g[16];
205 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
206 g[i] = bld.vgrf(BRW_TYPE_D);
207
208 brw_reg x = bld.vgrf(BRW_TYPE_D);
209 brw_reg y = bld.vgrf(BRW_TYPE_D);
210 emit_SEND(bld, x, g[1], g[2]);
211 bld.MUL( y, g[3], g[4]);
212 bld.AND( g[5], x, y);
213
214 brw_calculate_cfg(*v);
215 bblock_t *block0 = v->cfg->blocks[0];
216 ASSERT_EQ(0, block0->start_ip);
217 ASSERT_EQ(2, block0->end_ip);
218
219 lower_scoreboard(v);
220 ASSERT_EQ(0, block0->start_ip);
221 ASSERT_EQ(2, block0->end_ip);
222
223 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
224 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
225 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_testcase(1, 0, TGL_SBID_DST));
226 }
227
TEST_F(scoreboard_test,RAW_outoforder_outoforder)228 TEST_F(scoreboard_test, RAW_outoforder_outoforder)
229 {
230 brw_reg g[16];
231 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
232 g[i] = bld.vgrf(BRW_TYPE_D);
233
234 /* The second SEND depends on the first, and would need to refer to two
235 * SBIDs. Since it is not possible we expect a SYNC instruction to be
236 * added.
237 */
238 brw_reg x = bld.vgrf(BRW_TYPE_D);
239 emit_SEND(bld, x, g[1], g[2]);
240 emit_SEND(bld, g[3], x, g[4])->sfid++;
241
242 brw_calculate_cfg(*v);
243 bblock_t *block0 = v->cfg->blocks[0];
244 ASSERT_EQ(0, block0->start_ip);
245 ASSERT_EQ(1, block0->end_ip);
246
247 lower_scoreboard(v);
248 ASSERT_EQ(0, block0->start_ip);
249 ASSERT_EQ(2, block0->end_ip);
250
251 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
252
253 fs_inst *sync = instruction(block0, 1);
254 EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC);
255 EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_DST, 0));
256
257 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1));
258 }
259
TEST_F(scoreboard_test,WAR_inorder_inorder)260 TEST_F(scoreboard_test, WAR_inorder_inorder)
261 {
262 brw_reg g[16];
263 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
264 g[i] = bld.vgrf(BRW_TYPE_D);
265
266 brw_reg x = bld.vgrf(BRW_TYPE_D);
267 bld.ADD(g[1], x, g[2]);
268 bld.MUL(g[3], g[4], g[5]);
269 bld.AND( x, g[6], g[7]);
270
271 brw_calculate_cfg(*v);
272 bblock_t *block0 = v->cfg->blocks[0];
273 ASSERT_EQ(0, block0->start_ip);
274 ASSERT_EQ(2, block0->end_ip);
275
276 lower_scoreboard(v);
277 ASSERT_EQ(0, block0->start_ip);
278 ASSERT_EQ(2, block0->end_ip);
279
280 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
281 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
282 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_null());
283 }
284
TEST_F(scoreboard_test,WAR_inorder_outoforder)285 TEST_F(scoreboard_test, WAR_inorder_outoforder)
286 {
287 brw_reg g[16];
288 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
289 g[i] = bld.vgrf(BRW_TYPE_D);
290
291 brw_reg x = bld.vgrf(BRW_TYPE_D);
292 bld.ADD( g[1], x, g[2]);
293 bld.MUL( g[3], g[4], g[5]);
294 emit_SEND(bld, x, g[6], g[7]);
295
296 brw_calculate_cfg(*v);
297 bblock_t *block0 = v->cfg->blocks[0];
298 ASSERT_EQ(0, block0->start_ip);
299 ASSERT_EQ(2, block0->end_ip);
300
301 lower_scoreboard(v);
302 ASSERT_EQ(0, block0->start_ip);
303 ASSERT_EQ(2, block0->end_ip);
304
305 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
306 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
307 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_testcase(2, 0, TGL_SBID_SET));
308 }
309
TEST_F(scoreboard_test,WAR_outoforder_inorder)310 TEST_F(scoreboard_test, WAR_outoforder_inorder)
311 {
312 brw_reg g[16];
313 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
314 g[i] = bld.vgrf(BRW_TYPE_D);
315
316 brw_reg x = bld.vgrf(BRW_TYPE_D);
317 emit_SEND(bld, g[1], g[2], x);
318 bld.MUL( g[4], g[5], g[6]);
319 bld.AND( x, g[7], g[8]);
320
321 brw_calculate_cfg(*v);
322 bblock_t *block0 = v->cfg->blocks[0];
323 ASSERT_EQ(0, block0->start_ip);
324 ASSERT_EQ(2, block0->end_ip);
325
326 lower_scoreboard(v);
327 ASSERT_EQ(0, block0->start_ip);
328 ASSERT_EQ(2, block0->end_ip);
329
330 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
331 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
332 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SRC, 0));
333 }
334
TEST_F(scoreboard_test,WAR_outoforder_outoforder)335 TEST_F(scoreboard_test, WAR_outoforder_outoforder)
336 {
337 brw_reg g[16];
338 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
339 g[i] = bld.vgrf(BRW_TYPE_D);
340
341 brw_reg x = bld.vgrf(BRW_TYPE_D);
342 emit_SEND(bld, g[1], g[2], x);
343 emit_SEND(bld, x, g[3], g[4])->sfid++;
344
345 brw_calculate_cfg(*v);
346 bblock_t *block0 = v->cfg->blocks[0];
347 ASSERT_EQ(0, block0->start_ip);
348 ASSERT_EQ(1, block0->end_ip);
349
350 lower_scoreboard(v);
351 ASSERT_EQ(0, block0->start_ip);
352 ASSERT_EQ(2, block0->end_ip);
353
354 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
355
356 fs_inst *sync = instruction(block0, 1);
357 EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC);
358 EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_SRC, 0));
359
360 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1));
361 }
362
TEST_F(scoreboard_test,WAW_inorder_inorder)363 TEST_F(scoreboard_test, WAW_inorder_inorder)
364 {
365 brw_reg g[16];
366 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
367 g[i] = bld.vgrf(BRW_TYPE_D);
368
369 brw_reg x = bld.vgrf(BRW_TYPE_D);
370 bld.ADD( x, g[1], g[2]);
371 bld.MUL(g[3], g[4], g[5]);
372 bld.AND( x, g[6], g[7]);
373
374 brw_calculate_cfg(*v);
375 bblock_t *block0 = v->cfg->blocks[0];
376 ASSERT_EQ(0, block0->start_ip);
377 ASSERT_EQ(2, block0->end_ip);
378
379 lower_scoreboard(v);
380 ASSERT_EQ(0, block0->start_ip);
381 ASSERT_EQ(2, block0->end_ip);
382
383 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
384 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
385
386 /* NOTE: We only need this RegDist if a long instruction is followed by a
387 * short one. The pass is currently conservative about this and adding the
388 * annotation.
389 */
390 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_regdist(2));
391 }
392
TEST_F(scoreboard_test,WAW_inorder_outoforder)393 TEST_F(scoreboard_test, WAW_inorder_outoforder)
394 {
395 brw_reg g[16];
396 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
397 g[i] = bld.vgrf(BRW_TYPE_D);
398
399 brw_reg x = bld.vgrf(BRW_TYPE_D);
400 bld.ADD( x, g[1], g[2]);
401 bld.MUL( g[3], g[4], g[5]);
402 emit_SEND(bld, x, g[6], g[7]);
403
404 brw_calculate_cfg(*v);
405 bblock_t *block0 = v->cfg->blocks[0];
406 ASSERT_EQ(0, block0->start_ip);
407 ASSERT_EQ(2, block0->end_ip);
408
409 lower_scoreboard(v);
410 ASSERT_EQ(0, block0->start_ip);
411 ASSERT_EQ(2, block0->end_ip);
412
413 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
414 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
415 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_testcase(2, 0, TGL_SBID_SET));
416 }
417
TEST_F(scoreboard_test,WAW_outoforder_inorder)418 TEST_F(scoreboard_test, WAW_outoforder_inorder)
419 {
420 brw_reg g[16];
421 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
422 g[i] = bld.vgrf(BRW_TYPE_D);
423
424 brw_reg x = bld.vgrf(BRW_TYPE_D);
425 emit_SEND(bld, x, g[1], g[2]);
426 bld.MUL( g[3], g[4], g[5]);
427 bld.AND( x, g[6], g[7]);
428
429 brw_calculate_cfg(*v);
430 bblock_t *block0 = v->cfg->blocks[0];
431 ASSERT_EQ(0, block0->start_ip);
432 ASSERT_EQ(2, block0->end_ip);
433
434 lower_scoreboard(v);
435 ASSERT_EQ(0, block0->start_ip);
436 ASSERT_EQ(2, block0->end_ip);
437
438 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
439 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
440 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_DST, 0));
441 }
442
TEST_F(scoreboard_test,WAW_outoforder_outoforder)443 TEST_F(scoreboard_test, WAW_outoforder_outoforder)
444 {
445 brw_reg g[16];
446 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
447 g[i] = bld.vgrf(BRW_TYPE_D);
448
449 brw_reg x = bld.vgrf(BRW_TYPE_D);
450 emit_SEND(bld, x, g[1], g[2]);
451 emit_SEND(bld, x, g[3], g[4])->sfid++;
452
453 brw_calculate_cfg(*v);
454 bblock_t *block0 = v->cfg->blocks[0];
455 ASSERT_EQ(0, block0->start_ip);
456 ASSERT_EQ(1, block0->end_ip);
457
458 lower_scoreboard(v);
459 ASSERT_EQ(0, block0->start_ip);
460 ASSERT_EQ(2, block0->end_ip);
461
462 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0));
463
464 fs_inst *sync = instruction(block0, 1);
465 EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC);
466 EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_DST, 0));
467
468 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1));
469 }
470
471
TEST_F(scoreboard_test,loop1)472 TEST_F(scoreboard_test, loop1)
473 {
474 brw_reg g[16];
475 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
476 g[i] = bld.vgrf(BRW_TYPE_D);
477
478 brw_reg x = bld.vgrf(BRW_TYPE_D);
479 bld.XOR( x, g[1], g[2]);
480
481 bld.emit(BRW_OPCODE_DO);
482
483 bld.ADD( x, g[1], g[2]);
484 bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL;
485
486 bld.MUL( x, g[1], g[2]);
487
488 brw_calculate_cfg(*v);
489 lower_scoreboard(v);
490
491 bblock_t *body = v->cfg->blocks[2];
492 fs_inst *add = instruction(body, 0);
493 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
494 EXPECT_EQ(add->sched, tgl_swsb_regdist(1));
495
496 bblock_t *last_block = v->cfg->blocks[3];
497 fs_inst *mul = instruction(last_block, 0);
498 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
499 EXPECT_EQ(mul->sched, tgl_swsb_regdist(1));
500 }
501
TEST_F(scoreboard_test,loop2)502 TEST_F(scoreboard_test, loop2)
503 {
504 brw_reg g[16];
505 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
506 g[i] = bld.vgrf(BRW_TYPE_D);
507
508 brw_reg x = bld.vgrf(BRW_TYPE_D);
509 bld.XOR( x, g[1], g[2]);
510 bld.XOR(g[3], g[1], g[2]);
511 bld.XOR(g[4], g[1], g[2]);
512 bld.XOR(g[5], g[1], g[2]);
513
514 bld.emit(BRW_OPCODE_DO);
515
516 bld.ADD( x, g[1], g[2]);
517 bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL;
518
519 bld.MUL( x, g[1], g[2]);
520
521 brw_calculate_cfg(*v);
522 lower_scoreboard(v);
523
524 /* Now the write in ADD has the tightest RegDist for both ADD and MUL. */
525
526 bblock_t *body = v->cfg->blocks[2];
527 fs_inst *add = instruction(body, 0);
528 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
529 EXPECT_EQ(add->sched, tgl_swsb_regdist(2));
530
531 bblock_t *last_block = v->cfg->blocks[3];
532 fs_inst *mul = instruction(last_block, 0);
533 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
534 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
535 }
536
TEST_F(scoreboard_test,loop3)537 TEST_F(scoreboard_test, loop3)
538 {
539 brw_reg g[16];
540 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
541 g[i] = bld.vgrf(BRW_TYPE_D);
542
543 brw_reg x = bld.vgrf(BRW_TYPE_D);
544 bld.XOR( x, g[1], g[2]);
545
546 bld.emit(BRW_OPCODE_DO);
547
548 /* For the ADD in the loop body this extra distance will always apply. */
549 bld.XOR(g[3], g[1], g[2]);
550 bld.XOR(g[4], g[1], g[2]);
551 bld.XOR(g[5], g[1], g[2]);
552 bld.XOR(g[6], g[1], g[2]);
553
554 bld.ADD( x, g[1], g[2]);
555 bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL;
556
557 bld.MUL( x, g[1], g[2]);
558
559 brw_calculate_cfg(*v);
560 lower_scoreboard(v);
561
562 bblock_t *body = v->cfg->blocks[2];
563 fs_inst *add = instruction(body, 4);
564 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
565 EXPECT_EQ(add->sched, tgl_swsb_regdist(5));
566
567 bblock_t *last_block = v->cfg->blocks[3];
568 fs_inst *mul = instruction(last_block, 0);
569 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
570 EXPECT_EQ(mul->sched, tgl_swsb_regdist(1));
571 }
572
573
TEST_F(scoreboard_test,conditional1)574 TEST_F(scoreboard_test, conditional1)
575 {
576 brw_reg g[16];
577 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
578 g[i] = bld.vgrf(BRW_TYPE_D);
579
580 brw_reg x = bld.vgrf(BRW_TYPE_D);
581 bld.XOR( x, g[1], g[2]);
582 bld.emit(BRW_OPCODE_IF);
583
584 bld.ADD( x, g[1], g[2]);
585
586 bld.emit(BRW_OPCODE_ENDIF);
587 bld.MUL( x, g[1], g[2]);
588
589 brw_calculate_cfg(*v);
590 lower_scoreboard(v);
591
592 bblock_t *body = v->cfg->blocks[1];
593 fs_inst *add = instruction(body, 0);
594 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
595 EXPECT_EQ(add->sched, tgl_swsb_regdist(2));
596
597 bblock_t *last_block = v->cfg->blocks[2];
598 fs_inst *mul = instruction(last_block, 1);
599 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
600 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
601 }
602
TEST_F(scoreboard_test,conditional2)603 TEST_F(scoreboard_test, conditional2)
604 {
605 brw_reg g[16];
606 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
607 g[i] = bld.vgrf(BRW_TYPE_D);
608
609 brw_reg x = bld.vgrf(BRW_TYPE_D);
610 bld.XOR( x, g[1], g[2]);
611 bld.XOR(g[3], g[1], g[2]);
612 bld.XOR(g[4], g[1], g[2]);
613 bld.XOR(g[5], g[1], g[2]);
614 bld.emit(BRW_OPCODE_IF);
615
616 bld.ADD( x, g[1], g[2]);
617
618 bld.emit(BRW_OPCODE_ENDIF);
619 bld.MUL( x, g[1], g[2]);
620
621 brw_calculate_cfg(*v);
622 lower_scoreboard(v);
623
624 bblock_t *body = v->cfg->blocks[1];
625 fs_inst *add = instruction(body, 0);
626 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
627 EXPECT_EQ(add->sched, tgl_swsb_regdist(5));
628
629 bblock_t *last_block = v->cfg->blocks[2];
630 fs_inst *mul = instruction(last_block, 1);
631 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
632 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
633 }
634
TEST_F(scoreboard_test,conditional3)635 TEST_F(scoreboard_test, conditional3)
636 {
637 brw_reg g[16];
638 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
639 g[i] = bld.vgrf(BRW_TYPE_D);
640
641 brw_reg x = bld.vgrf(BRW_TYPE_D);
642 bld.XOR( x, g[1], g[2]);
643 bld.emit(BRW_OPCODE_IF);
644
645 bld.XOR(g[3], g[1], g[2]);
646 bld.XOR(g[4], g[1], g[2]);
647 bld.XOR(g[5], g[1], g[2]);
648 bld.ADD( x, g[1], g[2]);
649
650 bld.emit(BRW_OPCODE_ENDIF);
651 bld.MUL( x, g[1], g[2]);
652
653 brw_calculate_cfg(*v);
654 lower_scoreboard(v);
655
656 bblock_t *body = v->cfg->blocks[1];
657 fs_inst *add = instruction(body, 3);
658 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
659 EXPECT_EQ(add->sched, tgl_swsb_regdist(5));
660
661 bblock_t *last_block = v->cfg->blocks[2];
662 fs_inst *mul = instruction(last_block, 1);
663 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
664 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
665 }
666
TEST_F(scoreboard_test,conditional4)667 TEST_F(scoreboard_test, conditional4)
668 {
669 brw_reg g[16];
670 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
671 g[i] = bld.vgrf(BRW_TYPE_D);
672
673 brw_reg x = bld.vgrf(BRW_TYPE_D);
674 bld.XOR( x, g[1], g[2]);
675 bld.emit(BRW_OPCODE_IF);
676
677 bld.ADD( x, g[1], g[2]);
678 bld.XOR(g[3], g[1], g[2]);
679 bld.XOR(g[4], g[1], g[2]);
680 bld.XOR(g[5], g[1], g[2]);
681
682 bld.emit(BRW_OPCODE_ENDIF);
683 bld.MUL( x, g[1], g[2]);
684
685 brw_calculate_cfg(*v);
686 lower_scoreboard(v);
687
688 bblock_t *body = v->cfg->blocks[1];
689 fs_inst *add = instruction(body, 0);
690 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
691 EXPECT_EQ(add->sched, tgl_swsb_regdist(2));
692
693 bblock_t *last_block = v->cfg->blocks[2];
694 fs_inst *mul = instruction(last_block, 1);
695 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
696 EXPECT_EQ(mul->sched, tgl_swsb_regdist(3));
697 }
698
TEST_F(scoreboard_test,conditional5)699 TEST_F(scoreboard_test, conditional5)
700 {
701 brw_reg g[16];
702 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
703 g[i] = bld.vgrf(BRW_TYPE_D);
704
705 brw_reg x = bld.vgrf(BRW_TYPE_D);
706 bld.XOR( x, g[1], g[2]);
707 bld.emit(BRW_OPCODE_IF);
708
709 bld.ADD( x, g[1], g[2]);
710 bld.emit(BRW_OPCODE_ELSE);
711
712 bld.ROL( x, g[1], g[2]);
713
714 bld.emit(BRW_OPCODE_ENDIF);
715 bld.MUL( x, g[1], g[2]);
716
717 brw_calculate_cfg(*v);
718 lower_scoreboard(v);
719
720 bblock_t *then_body = v->cfg->blocks[1];
721 fs_inst *add = instruction(then_body, 0);
722 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
723 EXPECT_EQ(add->sched, tgl_swsb_regdist(2));
724
725 bblock_t *else_body = v->cfg->blocks[2];
726 fs_inst *rol = instruction(else_body, 0);
727 EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL);
728 EXPECT_EQ(rol->sched, tgl_swsb_regdist(2));
729
730 bblock_t *last_block = v->cfg->blocks[3];
731 fs_inst *mul = instruction(last_block, 1);
732 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
733 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
734 }
735
TEST_F(scoreboard_test,conditional6)736 TEST_F(scoreboard_test, conditional6)
737 {
738 brw_reg g[16];
739 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
740 g[i] = bld.vgrf(BRW_TYPE_D);
741
742 brw_reg x = bld.vgrf(BRW_TYPE_D);
743 bld.XOR( x, g[1], g[2]);
744 bld.emit(BRW_OPCODE_IF);
745
746 bld.XOR(g[3], g[1], g[2]);
747 bld.XOR(g[4], g[1], g[2]);
748 bld.XOR(g[5], g[1], g[2]);
749 bld.ADD( x, g[1], g[2]);
750 bld.emit(BRW_OPCODE_ELSE);
751
752 bld.XOR(g[6], g[1], g[2]);
753 bld.XOR(g[7], g[1], g[2]);
754 bld.XOR(g[8], g[1], g[2]);
755 bld.XOR(g[9], g[1], g[2]);
756 bld.ROL( x, g[1], g[2]);
757
758 bld.emit(BRW_OPCODE_ENDIF);
759 bld.MUL( x, g[1], g[2]);
760
761 brw_calculate_cfg(*v);
762 lower_scoreboard(v);
763
764 bblock_t *then_body = v->cfg->blocks[1];
765 fs_inst *add = instruction(then_body, 3);
766 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
767 EXPECT_EQ(add->sched, tgl_swsb_regdist(5));
768
769 bblock_t *else_body = v->cfg->blocks[2];
770 fs_inst *rol = instruction(else_body, 4);
771 EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL);
772 EXPECT_EQ(rol->sched, tgl_swsb_regdist(6));
773
774 bblock_t *last_block = v->cfg->blocks[3];
775 fs_inst *mul = instruction(last_block, 1);
776 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
777 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
778 }
779
TEST_F(scoreboard_test,conditional7)780 TEST_F(scoreboard_test, conditional7)
781 {
782 brw_reg g[16];
783 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
784 g[i] = bld.vgrf(BRW_TYPE_D);
785
786 brw_reg x = bld.vgrf(BRW_TYPE_D);
787 bld.XOR( x, g[1], g[2]);
788 bld.emit(BRW_OPCODE_IF);
789
790 bld.ADD( x, g[1], g[2]);
791 bld.XOR(g[3], g[1], g[2]);
792 bld.XOR(g[4], g[1], g[2]);
793 bld.XOR(g[5], g[1], g[2]);
794 bld.emit(BRW_OPCODE_ELSE);
795
796 bld.ROL( x, g[1], g[2]);
797 bld.XOR(g[6], g[1], g[2]);
798 bld.XOR(g[7], g[1], g[2]);
799 bld.XOR(g[8], g[1], g[2]);
800 bld.XOR(g[9], g[1], g[2]);
801
802 bld.emit(BRW_OPCODE_ENDIF);
803 bld.MUL( x, g[1], g[2]);
804
805 brw_calculate_cfg(*v);
806 lower_scoreboard(v);
807
808 bblock_t *then_body = v->cfg->blocks[1];
809 fs_inst *add = instruction(then_body, 0);
810 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
811 EXPECT_EQ(add->sched, tgl_swsb_regdist(2));
812
813 bblock_t *else_body = v->cfg->blocks[2];
814 fs_inst *rol = instruction(else_body, 0);
815 EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL);
816 EXPECT_EQ(rol->sched, tgl_swsb_regdist(2));
817
818 bblock_t *last_block = v->cfg->blocks[3];
819 fs_inst *mul = instruction(last_block, 1);
820 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
821 EXPECT_EQ(mul->sched, tgl_swsb_regdist(6));
822 }
823
TEST_F(scoreboard_test,conditional8)824 TEST_F(scoreboard_test, conditional8)
825 {
826 brw_reg g[16];
827 for (unsigned i = 0; i < ARRAY_SIZE(g); i++)
828 g[i] = bld.vgrf(BRW_TYPE_D);
829
830 brw_reg x = bld.vgrf(BRW_TYPE_D);
831 bld.XOR( x, g[1], g[2]);
832 bld.XOR(g[3], g[1], g[2]);
833 bld.XOR(g[4], g[1], g[2]);
834 bld.XOR(g[5], g[1], g[2]);
835 bld.XOR(g[6], g[1], g[2]);
836 bld.XOR(g[7], g[1], g[2]);
837 bld.emit(BRW_OPCODE_IF);
838
839 bld.ADD( x, g[1], g[2]);
840 bld.emit(BRW_OPCODE_ELSE);
841
842 bld.ROL( x, g[1], g[2]);
843
844 bld.emit(BRW_OPCODE_ENDIF);
845 bld.MUL( x, g[1], g[2]);
846
847 brw_calculate_cfg(*v);
848 lower_scoreboard(v);
849
850 bblock_t *then_body = v->cfg->blocks[1];
851 fs_inst *add = instruction(then_body, 0);
852 EXPECT_EQ(add->opcode, BRW_OPCODE_ADD);
853 EXPECT_EQ(add->sched, tgl_swsb_regdist(7));
854
855 /* Note that the ROL will have RegDist 2 and not 7, illustrating the
856 * physical CFG edge between the then-block and the else-block.
857 */
858 bblock_t *else_body = v->cfg->blocks[2];
859 fs_inst *rol = instruction(else_body, 0);
860 EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL);
861 EXPECT_EQ(rol->sched, tgl_swsb_regdist(2));
862
863 bblock_t *last_block = v->cfg->blocks[3];
864 fs_inst *mul = instruction(last_block, 1);
865 EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL);
866 EXPECT_EQ(mul->sched, tgl_swsb_regdist(2));
867 }
868
TEST_F(scoreboard_test,gfx125_RaR_over_different_pipes)869 TEST_F(scoreboard_test, gfx125_RaR_over_different_pipes)
870 {
871 devinfo->verx10 = 125;
872 brw_init_isa_info(&compiler->isa, devinfo);
873
874 brw_reg a = bld.vgrf(BRW_TYPE_D);
875 brw_reg b = bld.vgrf(BRW_TYPE_D);
876 brw_reg f = bld.vgrf(BRW_TYPE_F);
877 brw_reg x = bld.vgrf(BRW_TYPE_D);
878
879 bld.ADD(f, x, x);
880 bld.ADD(a, x, x);
881 bld.ADD(x, b, b);
882
883 brw_calculate_cfg(*v);
884 bblock_t *block0 = v->cfg->blocks[0];
885 ASSERT_EQ(0, block0->start_ip);
886 ASSERT_EQ(2, block0->end_ip);
887
888 lower_scoreboard(v);
889 ASSERT_EQ(0, block0->start_ip);
890 ASSERT_EQ(2, block0->end_ip);
891
892 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
893 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null());
894 EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_regdist(1));
895 }
896
TEST_F(scoreboard_test,gitlab_issue_from_mr_29723)897 TEST_F(scoreboard_test, gitlab_issue_from_mr_29723)
898 {
899 brw_init_isa_info(&compiler->isa, devinfo);
900
901 struct brw_reg a = brw_ud8_grf(29, 0);
902 struct brw_reg b = brw_ud8_grf(2, 0);
903
904 auto bld1 = bld.exec_all().group(1, 0);
905 bld1.ADD( a, stride(b, 0, 1, 0), brw_imm_ud(256));
906 bld1.CMP(brw_null_reg(), stride(a, 2, 1, 2), stride(b, 0, 1, 0), BRW_CONDITIONAL_L);
907
908 brw_calculate_cfg(*v);
909 bblock_t *block0 = v->cfg->blocks[0];
910 ASSERT_EQ(0, block0->start_ip);
911 ASSERT_EQ(1, block0->end_ip);
912
913 lower_scoreboard(v);
914 ASSERT_EQ(0, block0->start_ip);
915 ASSERT_EQ(1, block0->end_ip);
916
917 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
918 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_regdist(1));
919 }
920
TEST_F(scoreboard_test,gitlab_issue_11069)921 TEST_F(scoreboard_test, gitlab_issue_11069)
922 {
923 brw_init_isa_info(&compiler->isa, devinfo);
924
925 struct brw_reg a = brw_ud8_grf(76, 0);
926 struct brw_reg b = brw_ud8_grf(2, 0);
927
928 auto bld1 = bld.exec_all().group(1, 0);
929 bld1.ADD(stride(a, 2, 1, 2), stride(b, 0, 1, 0), brw_imm_ud(0x80));
930 bld1.CMP( brw_null_reg(), stride(a, 0, 1, 0), stride(b, 0, 1, 0), BRW_CONDITIONAL_L);
931
932 brw_calculate_cfg(*v);
933 bblock_t *block0 = v->cfg->blocks[0];
934 ASSERT_EQ(0, block0->start_ip);
935 ASSERT_EQ(1, block0->end_ip);
936
937 lower_scoreboard(v);
938 ASSERT_EQ(0, block0->start_ip);
939 ASSERT_EQ(1, block0->end_ip);
940
941 EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null());
942 EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_regdist(1));
943 }
944