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