1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <gtest/gtest.h>
25 #include "brw_fs.h"
26 #include "brw_fs_builder.h"
27 #include "brw_cfg.h"
28
29 using namespace brw;
30
31 class copy_propagation_test : public ::testing::Test {
32 protected:
33 copy_propagation_test();
34 ~copy_propagation_test() override;
35
36 struct brw_compiler *compiler;
37 struct brw_compile_params params;
38 struct intel_device_info *devinfo;
39 void *ctx;
40 struct brw_wm_prog_data *prog_data;
41 struct gl_shader_program *shader_prog;
42 fs_visitor *v;
43 fs_builder bld;
44 };
45
46 class copy_propagation_fs_visitor : public fs_visitor
47 {
48 public:
copy_propagation_fs_visitor(struct brw_compiler * compiler,struct brw_compile_params * params,struct brw_wm_prog_data * prog_data,nir_shader * shader)49 copy_propagation_fs_visitor(struct brw_compiler *compiler,
50 struct brw_compile_params *params,
51 struct brw_wm_prog_data *prog_data,
52 nir_shader *shader)
53 : fs_visitor(compiler, params, NULL,
54 &prog_data->base, shader, 8, false, false) {}
55 };
56
57
copy_propagation_test()58 copy_propagation_test::copy_propagation_test()
59 : bld(NULL, 0)
60 {
61 ctx = ralloc_context(NULL);
62 compiler = rzalloc(ctx, struct brw_compiler);
63 devinfo = rzalloc(ctx, struct intel_device_info);
64 compiler->devinfo = devinfo;
65
66 params = {};
67 params.mem_ctx = ctx;
68
69 prog_data = ralloc(ctx, struct brw_wm_prog_data);
70 nir_shader *shader =
71 nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
72
73 v = new copy_propagation_fs_visitor(compiler, ¶ms, prog_data, shader);
74
75 bld = fs_builder(v).at_end();
76
77 devinfo->ver = 9;
78 devinfo->verx10 = devinfo->ver * 10;
79 }
80
~copy_propagation_test()81 copy_propagation_test::~copy_propagation_test()
82 {
83 delete v;
84 v = NULL;
85
86 ralloc_free(ctx);
87 ctx = NULL;
88 }
89
90 static fs_inst *
instruction(bblock_t * block,int num)91 instruction(bblock_t *block, int num)
92 {
93 fs_inst *inst = (fs_inst *)block->start();
94 for (int i = 0; i < num; i++) {
95 inst = (fs_inst *)inst->next;
96 }
97 return inst;
98 }
99
100 static bool
copy_propagation(fs_visitor * v)101 copy_propagation(fs_visitor *v)
102 {
103 const bool print = getenv("TEST_DEBUG");
104
105 if (print) {
106 fprintf(stderr, "= Before =\n");
107 v->cfg->dump();
108 }
109
110 bool ret = brw_fs_opt_copy_propagation(*v);
111
112 if (print) {
113 fprintf(stderr, "\n= After =\n");
114 v->cfg->dump();
115 }
116
117 return ret;
118 }
119
TEST_F(copy_propagation_test,basic)120 TEST_F(copy_propagation_test, basic)
121 {
122 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_F);
123 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_F);
124 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_F);
125 brw_reg vgrf3 = bld.vgrf(BRW_TYPE_F);
126 bld.MOV(vgrf0, vgrf2);
127 bld.ADD(vgrf1, vgrf0, vgrf3);
128
129 /* = Before =
130 *
131 * 0: mov(8) vgrf0 vgrf2
132 * 1: add(8) vgrf1 vgrf0 vgrf3
133 *
134 * = After =
135 * 0: mov(8) vgrf0 vgrf2
136 * 1: add(8) vgrf1 vgrf2 vgrf3
137 */
138
139 brw_calculate_cfg(*v);
140 bblock_t *block0 = v->cfg->blocks[0];
141
142 EXPECT_EQ(0, block0->start_ip);
143 EXPECT_EQ(1, block0->end_ip);
144
145 EXPECT_TRUE(copy_propagation(v));
146 EXPECT_EQ(0, block0->start_ip);
147 EXPECT_EQ(1, block0->end_ip);
148
149 fs_inst *mov = instruction(block0, 0);
150 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
151 EXPECT_TRUE(mov->dst.equals(vgrf0));
152 EXPECT_TRUE(mov->src[0].equals(vgrf2));
153
154 fs_inst *add = instruction(block0, 1);
155 EXPECT_EQ(BRW_OPCODE_ADD, add->opcode);
156 EXPECT_TRUE(add->dst.equals(vgrf1));
157 EXPECT_TRUE(add->src[0].equals(vgrf2));
158 EXPECT_TRUE(add->src[1].equals(vgrf3));
159 }
160
TEST_F(copy_propagation_test,maxmax_sat_imm)161 TEST_F(copy_propagation_test, maxmax_sat_imm)
162 {
163 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_F);
164 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_F);
165 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_F);
166
167 static const struct {
168 enum brw_conditional_mod conditional_mod;
169 float immediate;
170 bool expected_result;
171 } test[] = {
172 /* conditional mod, imm, expected_result */
173 { BRW_CONDITIONAL_GE , 0.1f, false },
174 { BRW_CONDITIONAL_L , 0.1f, false },
175 { BRW_CONDITIONAL_GE , 0.5f, false },
176 { BRW_CONDITIONAL_L , 0.5f, false },
177 { BRW_CONDITIONAL_GE , 0.9f, false },
178 { BRW_CONDITIONAL_L , 0.9f, false },
179 { BRW_CONDITIONAL_GE , -1.5f, false },
180 { BRW_CONDITIONAL_L , -1.5f, false },
181 { BRW_CONDITIONAL_GE , 1.5f, false },
182 { BRW_CONDITIONAL_L , 1.5f, false },
183
184 { BRW_CONDITIONAL_NONE, 0.5f, false },
185 { BRW_CONDITIONAL_Z , 0.5f, false },
186 { BRW_CONDITIONAL_NZ , 0.5f, false },
187 { BRW_CONDITIONAL_G , 0.5f, false },
188 { BRW_CONDITIONAL_LE , 0.5f, false },
189 { BRW_CONDITIONAL_R , 0.5f, false },
190 { BRW_CONDITIONAL_O , 0.5f, false },
191 { BRW_CONDITIONAL_U , 0.5f, false },
192 };
193
194 for (unsigned i = 0; i < sizeof(test) / sizeof(test[0]); i++) {
195 fs_inst *mov = set_saturate(true, bld.MOV(vgrf0, vgrf1));
196 fs_inst *sel = set_condmod(test[i].conditional_mod,
197 bld.SEL(vgrf2, vgrf0,
198 brw_imm_f(test[i].immediate)));
199
200 brw_calculate_cfg(*v);
201
202 bblock_t *block0 = v->cfg->blocks[0];
203
204 EXPECT_EQ(0, block0->start_ip);
205 EXPECT_EQ(1, block0->end_ip);
206
207 EXPECT_EQ(test[i].expected_result, copy_propagation(v));
208 EXPECT_EQ(0, block0->start_ip);
209 EXPECT_EQ(1, block0->end_ip);
210
211 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
212 EXPECT_TRUE(mov->saturate);
213 EXPECT_TRUE(mov->dst.equals(vgrf0));
214 EXPECT_TRUE(mov->src[0].equals(vgrf1));
215
216 EXPECT_EQ(BRW_OPCODE_SEL, sel->opcode);
217 EXPECT_EQ(test[i].conditional_mod, sel->conditional_mod);
218 EXPECT_EQ(test[i].expected_result, sel->saturate);
219 EXPECT_TRUE(sel->dst.equals(vgrf2));
220 if (test[i].expected_result) {
221 EXPECT_TRUE(sel->src[0].equals(vgrf1));
222 } else {
223 EXPECT_TRUE(sel->src[0].equals(vgrf0));
224 }
225 EXPECT_TRUE(sel->src[1].equals(brw_imm_f(test[i].immediate)));
226
227 delete v->cfg;
228 v->cfg = NULL;
229 }
230 }
231
TEST_F(copy_propagation_test,mixed_integer_sign)232 TEST_F(copy_propagation_test, mixed_integer_sign)
233 {
234 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_UD);
235 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_D);
236 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_UD);
237 brw_reg vgrf3 = bld.vgrf(BRW_TYPE_UD);
238 brw_reg vgrf4 = bld.vgrf(BRW_TYPE_UD);
239
240 bld.MOV(vgrf1, vgrf0);
241 bld.BFE(vgrf2, vgrf3, vgrf4, retype(vgrf1, BRW_TYPE_UD));
242
243 /* = Before =
244 *
245 * 0: mov(8) vgrf1:D vgrf0:UD
246 * 1: bfe(8) vgrf2:UD vgrf3:UD vgrf4:UD vgrf1:UD
247 *
248 * = After =
249 * 0: mov(8) vgrf1:D vgrf0:UD
250 * 1: bfe(8) vgrf2:UD vgrf3:UD vgrf4:UD vgrf0:UD
251 */
252
253 brw_calculate_cfg(*v);
254 bblock_t *block0 = v->cfg->blocks[0];
255
256 EXPECT_EQ(0, block0->start_ip);
257 EXPECT_EQ(1, block0->end_ip);
258
259 EXPECT_TRUE(copy_propagation(v));
260 EXPECT_EQ(0, block0->start_ip);
261 EXPECT_EQ(1, block0->end_ip);
262
263 fs_inst *mov = instruction(block0, 0);
264 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
265 EXPECT_TRUE(mov->dst.equals(vgrf1));
266 EXPECT_TRUE(mov->src[0].equals(vgrf0));
267
268 fs_inst *bfe = instruction(block0, 1);
269 EXPECT_EQ(BRW_OPCODE_BFE, bfe->opcode);
270 EXPECT_TRUE(bfe->dst.equals(vgrf2));
271 EXPECT_TRUE(bfe->src[0].equals(vgrf3));
272 EXPECT_TRUE(bfe->src[1].equals(vgrf4));
273 EXPECT_TRUE(bfe->src[2].equals(vgrf0));
274 }
275
TEST_F(copy_propagation_test,mixed_integer_sign_with_vector_imm)276 TEST_F(copy_propagation_test, mixed_integer_sign_with_vector_imm)
277 {
278 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_W);
279 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_UD);
280 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_UD);
281
282 bld.MOV(vgrf0, brw_imm_uv(0xffff));
283 bld.ADD(vgrf1, vgrf2, retype(vgrf0, BRW_TYPE_UW));
284
285 /* = Before =
286 *
287 * 0: mov(8) vgrf0:W ...:UV
288 * 1: add(8) vgrf1:UD vgrf2:UD vgrf0:UW
289 *
290 * = After =
291 * No change
292 */
293
294 brw_calculate_cfg(*v);
295 bblock_t *block0 = v->cfg->blocks[0];
296
297 const brw_reg src1 = instruction(block0, 1)->src[1];
298
299 EXPECT_EQ(0, block0->start_ip);
300 EXPECT_EQ(1, block0->end_ip);
301
302 EXPECT_FALSE(copy_propagation(v));
303 EXPECT_EQ(0, block0->start_ip);
304 EXPECT_EQ(1, block0->end_ip);
305
306 fs_inst *mov = instruction(block0, 0);
307 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
308 EXPECT_TRUE(mov->dst.equals(vgrf0));
309 EXPECT_TRUE(mov->src[0].file == IMM);
310
311 fs_inst *add = instruction(block0, 1);
312 EXPECT_EQ(BRW_OPCODE_ADD, add->opcode);
313 EXPECT_TRUE(add->dst.equals(vgrf1));
314 EXPECT_TRUE(add->src[0].equals(vgrf2));
315 EXPECT_TRUE(add->src[1].equals(src1));
316 }
317