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