i965/vec4: Init mlen for several send from GRF instructions.
[mesa.git] / src / mesa / drivers / dri / i965 / test_fs_cmod_propagation.cpp
1 /*
2 * Copyright © 2015 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 class cmod_propagation_test : public ::testing::Test {
30 virtual void SetUp();
31
32 public:
33 struct brw_context *brw;
34 struct gl_context *ctx;
35 struct brw_wm_prog_data *prog_data;
36 struct gl_shader_program *shader_prog;
37 struct brw_fragment_program *fp;
38 fs_visitor *v;
39 };
40
41 class cmod_propagation_fs_visitor : public fs_visitor
42 {
43 public:
44 cmod_propagation_fs_visitor(struct brw_context *brw,
45 struct brw_wm_prog_data *prog_data,
46 struct gl_shader_program *shader_prog)
47 : fs_visitor(brw, NULL, NULL, prog_data, shader_prog, NULL, 8) {}
48 };
49
50
51 void cmod_propagation_test::SetUp()
52 {
53 brw = (struct brw_context *)calloc(1, sizeof(*brw));
54 ctx = &brw->ctx;
55
56 fp = ralloc(NULL, struct brw_fragment_program);
57 prog_data = ralloc(NULL, struct brw_wm_prog_data);
58 shader_prog = ralloc(NULL, struct gl_shader_program);
59
60 v = new cmod_propagation_fs_visitor(brw, prog_data, shader_prog);
61
62 _mesa_init_fragment_program(ctx, &fp->program, GL_FRAGMENT_SHADER, 0);
63
64 brw->gen = 4;
65 }
66
67 static fs_inst *
68 instruction(bblock_t *block, int num)
69 {
70 fs_inst *inst = (fs_inst *)block->start();
71 for (int i = 0; i < num; i++) {
72 inst = (fs_inst *)inst->next;
73 }
74 return inst;
75 }
76
77 static bool
78 cmod_propagation(fs_visitor *v)
79 {
80 const bool print = false;
81
82 if (print) {
83 fprintf(stderr, "= Before =\n");
84 v->cfg->dump(v);
85 }
86
87 bool ret = v->opt_cmod_propagation();
88
89 if (print) {
90 fprintf(stderr, "\n= After =\n");
91 v->cfg->dump(v);
92 }
93
94 return ret;
95 }
96
97 TEST_F(cmod_propagation_test, basic)
98 {
99 fs_reg dest = v->vgrf(glsl_type::float_type);
100 fs_reg src0 = v->vgrf(glsl_type::float_type);
101 fs_reg src1 = v->vgrf(glsl_type::float_type);
102 fs_reg zero(0.0f);
103 v->emit(BRW_OPCODE_ADD, dest, src0, src1);
104 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest, zero)
105 ->conditional_mod = BRW_CONDITIONAL_GE;
106
107 /* = Before =
108 *
109 * 0: add(8) dest src0 src1
110 * 1: cmp.ge.f0(8) null dest 0.0f
111 *
112 * = After =
113 * 0: add.ge.f0(8) dest src0 src1
114 */
115
116 v->calculate_cfg();
117 bblock_t *block0 = v->cfg->blocks[0];
118
119 EXPECT_EQ(0, block0->start_ip);
120 EXPECT_EQ(1, block0->end_ip);
121
122 EXPECT_TRUE(cmod_propagation(v));
123 EXPECT_EQ(0, block0->start_ip);
124 EXPECT_EQ(0, block0->end_ip);
125 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
126 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
127 }
128
129 TEST_F(cmod_propagation_test, cmp_nonzero)
130 {
131 fs_reg dest = v->vgrf(glsl_type::float_type);
132 fs_reg src0 = v->vgrf(glsl_type::float_type);
133 fs_reg src1 = v->vgrf(glsl_type::float_type);
134 fs_reg nonzero(1.0f);
135 v->emit(BRW_OPCODE_ADD, dest, src0, src1);
136 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest, nonzero)
137 ->conditional_mod = BRW_CONDITIONAL_GE;
138
139 /* = Before =
140 *
141 * 0: add(8) dest src0 src1
142 * 1: cmp.ge.f0(8) null dest 1.0f
143 *
144 * = After =
145 * (no changes)
146 */
147
148 v->calculate_cfg();
149 bblock_t *block0 = v->cfg->blocks[0];
150
151 EXPECT_EQ(0, block0->start_ip);
152 EXPECT_EQ(1, block0->end_ip);
153
154 EXPECT_FALSE(cmod_propagation(v));
155 EXPECT_EQ(0, block0->start_ip);
156 EXPECT_EQ(1, block0->end_ip);
157 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
158 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
159 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
160 }
161
162 TEST_F(cmod_propagation_test, non_cmod_instruction)
163 {
164 fs_reg dest = v->vgrf(glsl_type::uint_type);
165 fs_reg src0 = v->vgrf(glsl_type::uint_type);
166 fs_reg zero(0u);
167 v->emit(BRW_OPCODE_FBL, dest, src0);
168 v->emit(BRW_OPCODE_CMP, v->reg_null_ud, dest, zero)
169 ->conditional_mod = BRW_CONDITIONAL_GE;
170
171 /* = Before =
172 *
173 * 0: fbl(8) dest src0
174 * 1: cmp.ge.f0(8) null dest 0u
175 *
176 * = After =
177 * (no changes)
178 */
179
180 v->calculate_cfg();
181 bblock_t *block0 = v->cfg->blocks[0];
182
183 EXPECT_EQ(0, block0->start_ip);
184 EXPECT_EQ(1, block0->end_ip);
185
186 EXPECT_FALSE(cmod_propagation(v));
187 EXPECT_EQ(0, block0->start_ip);
188 EXPECT_EQ(1, block0->end_ip);
189 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
190 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
191 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
192 }
193
194 TEST_F(cmod_propagation_test, intervening_flag_write)
195 {
196 fs_reg dest = v->vgrf(glsl_type::float_type);
197 fs_reg src0 = v->vgrf(glsl_type::float_type);
198 fs_reg src1 = v->vgrf(glsl_type::float_type);
199 fs_reg src2 = v->vgrf(glsl_type::float_type);
200 fs_reg zero(0.0f);
201 v->emit(BRW_OPCODE_ADD, dest, src0, src1);
202 v->emit(BRW_OPCODE_CMP, v->reg_null_f, src2, zero)
203 ->conditional_mod = BRW_CONDITIONAL_GE;
204 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest, zero)
205 ->conditional_mod = BRW_CONDITIONAL_GE;
206
207 /* = Before =
208 *
209 * 0: add(8) dest src0 src1
210 * 1: cmp.ge.f0(8) null src2 0.0f
211 * 2: cmp.ge.f0(8) null dest 0.0f
212 *
213 * = After =
214 * (no changes)
215 */
216
217 v->calculate_cfg();
218 bblock_t *block0 = v->cfg->blocks[0];
219
220 EXPECT_EQ(0, block0->start_ip);
221 EXPECT_EQ(2, block0->end_ip);
222
223 EXPECT_FALSE(cmod_propagation(v));
224 EXPECT_EQ(0, block0->start_ip);
225 EXPECT_EQ(2, block0->end_ip);
226 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
227 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
228 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
229 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
230 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
231 }
232
233 TEST_F(cmod_propagation_test, intervening_flag_read)
234 {
235 fs_reg dest0 = v->vgrf(glsl_type::float_type);
236 fs_reg dest1 = v->vgrf(glsl_type::float_type);
237 fs_reg src0 = v->vgrf(glsl_type::float_type);
238 fs_reg src1 = v->vgrf(glsl_type::float_type);
239 fs_reg src2 = v->vgrf(glsl_type::float_type);
240 fs_reg zero(0.0f);
241 v->emit(BRW_OPCODE_ADD, dest0, src0, src1);
242 v->emit(BRW_OPCODE_SEL, dest1, src2, zero)
243 ->predicate = BRW_PREDICATE_NORMAL;
244 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest0, zero)
245 ->conditional_mod = BRW_CONDITIONAL_GE;
246
247 /* = Before =
248 *
249 * 0: add(8) dest0 src0 src1
250 * 1: (+f0) sel(8) dest1 src2 0.0f
251 * 2: cmp.ge.f0(8) null dest0 0.0f
252 *
253 * = After =
254 * (no changes)
255 */
256
257 v->calculate_cfg();
258 bblock_t *block0 = v->cfg->blocks[0];
259
260 EXPECT_EQ(0, block0->start_ip);
261 EXPECT_EQ(2, block0->end_ip);
262
263 EXPECT_FALSE(cmod_propagation(v));
264 EXPECT_EQ(0, block0->start_ip);
265 EXPECT_EQ(2, block0->end_ip);
266 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
267 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
268 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
269 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
270 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
271 }
272
273 TEST_F(cmod_propagation_test, intervening_dest_write)
274 {
275 fs_reg dest = v->vgrf(glsl_type::vec4_type);
276 fs_reg src0 = v->vgrf(glsl_type::float_type);
277 fs_reg src1 = v->vgrf(glsl_type::float_type);
278 fs_reg src2 = v->vgrf(glsl_type::vec2_type);
279 fs_reg zero(0.0f);
280 v->emit(BRW_OPCODE_ADD, offset(dest, 2), src0, src1);
281 v->emit(SHADER_OPCODE_TEX, dest, src2)
282 ->regs_written = 4;
283 v->emit(BRW_OPCODE_CMP, v->reg_null_f, offset(dest, 2), zero)
284 ->conditional_mod = BRW_CONDITIONAL_GE;
285
286 /* = Before =
287 *
288 * 0: add(8) dest+2 src0 src1
289 * 1: tex(8) rlen 4 dest+0 src2
290 * 2: cmp.ge.f0(8) null dest+2 0.0f
291 *
292 * = After =
293 * (no changes)
294 */
295
296 v->calculate_cfg();
297 bblock_t *block0 = v->cfg->blocks[0];
298
299 EXPECT_EQ(0, block0->start_ip);
300 EXPECT_EQ(2, block0->end_ip);
301
302 EXPECT_FALSE(cmod_propagation(v));
303 EXPECT_EQ(0, block0->start_ip);
304 EXPECT_EQ(2, block0->end_ip);
305 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
306 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
307 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
308 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
309 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
310 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
311 }
312
313 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
314 {
315 fs_reg dest0 = v->vgrf(glsl_type::float_type);
316 fs_reg dest1 = v->vgrf(glsl_type::float_type);
317 fs_reg src0 = v->vgrf(glsl_type::float_type);
318 fs_reg src1 = v->vgrf(glsl_type::float_type);
319 fs_reg src2 = v->vgrf(glsl_type::float_type);
320 fs_reg zero(0.0f);
321 v->emit(BRW_OPCODE_ADD, dest0, src0, src1)
322 ->conditional_mod = BRW_CONDITIONAL_GE;
323 v->emit(BRW_OPCODE_SEL, dest1, src2, zero)
324 ->predicate = BRW_PREDICATE_NORMAL;
325 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest0, zero)
326 ->conditional_mod = BRW_CONDITIONAL_GE;
327
328 /* = Before =
329 *
330 * 0: add.ge.f0(8) dest0 src0 src1
331 * 1: (+f0) sel(8) dest1 src2 0.0f
332 * 2: cmp.ge.f0(8) null dest0 0.0f
333 *
334 * = After =
335 * 0: add.ge.f0(8) dest0 src0 src1
336 * 1: (+f0) sel(8) dest1 src2 0.0f
337 */
338
339 v->calculate_cfg();
340 bblock_t *block0 = v->cfg->blocks[0];
341
342 EXPECT_EQ(0, block0->start_ip);
343 EXPECT_EQ(2, block0->end_ip);
344
345 EXPECT_TRUE(cmod_propagation(v));
346 EXPECT_EQ(0, block0->start_ip);
347 EXPECT_EQ(1, block0->end_ip);
348 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
349 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
350 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
351 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
352 }
353
354 TEST_F(cmod_propagation_test, negate)
355 {
356 fs_reg dest = v->vgrf(glsl_type::float_type);
357 fs_reg src0 = v->vgrf(glsl_type::float_type);
358 fs_reg src1 = v->vgrf(glsl_type::float_type);
359 fs_reg zero(0.0f);
360 v->emit(BRW_OPCODE_ADD, dest, src0, src1);
361 dest.negate = true;
362 v->emit(BRW_OPCODE_CMP, v->reg_null_f, dest, zero)
363 ->conditional_mod = BRW_CONDITIONAL_GE;
364
365 /* = Before =
366 *
367 * 0: add(8) dest src0 src1
368 * 1: cmp.ge.f0(8) null -dest 0.0f
369 *
370 * = After =
371 * 0: add.le.f0(8) dest src0 src1
372 */
373
374 v->calculate_cfg();
375 bblock_t *block0 = v->cfg->blocks[0];
376
377 EXPECT_EQ(0, block0->start_ip);
378 EXPECT_EQ(1, block0->end_ip);
379
380 EXPECT_TRUE(cmod_propagation(v));
381 EXPECT_EQ(0, block0->start_ip);
382 EXPECT_EQ(0, block0->end_ip);
383 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
384 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
385 }
386
387 TEST_F(cmod_propagation_test, movnz)
388 {
389 fs_reg dest = v->vgrf(glsl_type::float_type);
390 fs_reg src0 = v->vgrf(glsl_type::float_type);
391 fs_reg src1 = v->vgrf(glsl_type::float_type);
392 v->emit(BRW_OPCODE_CMP, dest, src0, src1)
393 ->conditional_mod = BRW_CONDITIONAL_GE;
394 v->emit(BRW_OPCODE_MOV, v->reg_null_f, dest)
395 ->conditional_mod = BRW_CONDITIONAL_NZ;
396
397 /* = Before =
398 *
399 * 0: cmp.ge.f0(8) dest src0 src1
400 * 1: mov.nz.f0(8) null dest
401 *
402 * = After =
403 * 0: cmp.ge.f0(8) dest src0 src1
404 */
405
406 v->calculate_cfg();
407 bblock_t *block0 = v->cfg->blocks[0];
408
409 EXPECT_EQ(0, block0->start_ip);
410 EXPECT_EQ(1, block0->end_ip);
411
412 EXPECT_TRUE(cmod_propagation(v));
413 EXPECT_EQ(0, block0->start_ip);
414 EXPECT_EQ(0, block0->end_ip);
415 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
416 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
417 }