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