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_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 brw_builder bld;
44 };
45
copy_propagation_test()46 copy_propagation_test::copy_propagation_test()
47 : bld(NULL, 0)
48 {
49 ctx = ralloc_context(NULL);
50 compiler = rzalloc(ctx, struct brw_compiler);
51 devinfo = rzalloc(ctx, struct intel_device_info);
52 compiler->devinfo = devinfo;
53
54 params = {};
55 params.mem_ctx = ctx;
56
57 prog_data = ralloc(ctx, struct brw_wm_prog_data);
58 nir_shader *shader =
59 nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
60
61 v = new fs_visitor(compiler, ¶ms, NULL, &prog_data->base, shader,
62 8, false, false);
63
64 bld = brw_builder(v).at_end();
65
66 devinfo->ver = 9;
67 devinfo->verx10 = devinfo->ver * 10;
68 }
69
~copy_propagation_test()70 copy_propagation_test::~copy_propagation_test()
71 {
72 delete v;
73 v = NULL;
74
75 ralloc_free(ctx);
76 ctx = NULL;
77 }
78
79 static fs_inst *
instruction(bblock_t * block,int num)80 instruction(bblock_t *block, int num)
81 {
82 fs_inst *inst = (fs_inst *)block->start();
83 for (int i = 0; i < num; i++) {
84 inst = (fs_inst *)inst->next;
85 }
86 return inst;
87 }
88
89 static bool
copy_propagation(fs_visitor * v)90 copy_propagation(fs_visitor *v)
91 {
92 const bool print = getenv("TEST_DEBUG");
93
94 if (print) {
95 fprintf(stderr, "= Before =\n");
96 v->cfg->dump();
97 }
98
99 bool ret = brw_opt_copy_propagation(*v);
100
101 if (print) {
102 fprintf(stderr, "\n= After =\n");
103 v->cfg->dump();
104 }
105
106 return ret;
107 }
108
TEST_F(copy_propagation_test,basic)109 TEST_F(copy_propagation_test, basic)
110 {
111 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_F);
112 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_F);
113 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_F);
114 brw_reg vgrf3 = bld.vgrf(BRW_TYPE_F);
115 bld.MOV(vgrf0, vgrf2);
116 bld.ADD(vgrf1, vgrf0, vgrf3);
117
118 /* = Before =
119 *
120 * 0: mov(8) vgrf0 vgrf2
121 * 1: add(8) vgrf1 vgrf0 vgrf3
122 *
123 * = After =
124 * 0: mov(8) vgrf0 vgrf2
125 * 1: add(8) vgrf1 vgrf2 vgrf3
126 */
127
128 brw_calculate_cfg(*v);
129 bblock_t *block0 = v->cfg->blocks[0];
130
131 EXPECT_EQ(0, block0->start_ip);
132 EXPECT_EQ(1, block0->end_ip);
133
134 EXPECT_TRUE(copy_propagation(v));
135 EXPECT_EQ(0, block0->start_ip);
136 EXPECT_EQ(1, block0->end_ip);
137
138 fs_inst *mov = instruction(block0, 0);
139 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
140 EXPECT_TRUE(mov->dst.equals(vgrf0));
141 EXPECT_TRUE(mov->src[0].equals(vgrf2));
142
143 fs_inst *add = instruction(block0, 1);
144 EXPECT_EQ(BRW_OPCODE_ADD, add->opcode);
145 EXPECT_TRUE(add->dst.equals(vgrf1));
146 EXPECT_TRUE(add->src[0].equals(vgrf2));
147 EXPECT_TRUE(add->src[1].equals(vgrf3));
148 }
149
TEST_F(copy_propagation_test,maxmax_sat_imm)150 TEST_F(copy_propagation_test, maxmax_sat_imm)
151 {
152 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_F);
153 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_F);
154 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_F);
155
156 static const struct {
157 enum brw_conditional_mod conditional_mod;
158 float immediate;
159 bool expected_result;
160 } test[] = {
161 /* conditional mod, imm, expected_result */
162 { BRW_CONDITIONAL_GE , 0.1f, false },
163 { BRW_CONDITIONAL_L , 0.1f, false },
164 { BRW_CONDITIONAL_GE , 0.5f, false },
165 { BRW_CONDITIONAL_L , 0.5f, false },
166 { BRW_CONDITIONAL_GE , 0.9f, false },
167 { BRW_CONDITIONAL_L , 0.9f, false },
168 { BRW_CONDITIONAL_GE , -1.5f, false },
169 { BRW_CONDITIONAL_L , -1.5f, false },
170 { BRW_CONDITIONAL_GE , 1.5f, false },
171 { BRW_CONDITIONAL_L , 1.5f, false },
172
173 { BRW_CONDITIONAL_NONE, 0.5f, false },
174 { BRW_CONDITIONAL_Z , 0.5f, false },
175 { BRW_CONDITIONAL_NZ , 0.5f, false },
176 { BRW_CONDITIONAL_G , 0.5f, false },
177 { BRW_CONDITIONAL_LE , 0.5f, false },
178 { BRW_CONDITIONAL_R , 0.5f, false },
179 { BRW_CONDITIONAL_O , 0.5f, false },
180 { BRW_CONDITIONAL_U , 0.5f, false },
181 };
182
183 for (unsigned i = 0; i < sizeof(test) / sizeof(test[0]); i++) {
184 fs_inst *mov = set_saturate(true, bld.MOV(vgrf0, vgrf1));
185 fs_inst *sel = set_condmod(test[i].conditional_mod,
186 bld.SEL(vgrf2, vgrf0,
187 brw_imm_f(test[i].immediate)));
188
189 brw_calculate_cfg(*v);
190
191 bblock_t *block0 = v->cfg->blocks[0];
192
193 EXPECT_EQ(0, block0->start_ip);
194 EXPECT_EQ(1, block0->end_ip);
195
196 EXPECT_EQ(test[i].expected_result, copy_propagation(v));
197 EXPECT_EQ(0, block0->start_ip);
198 EXPECT_EQ(1, block0->end_ip);
199
200 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
201 EXPECT_TRUE(mov->saturate);
202 EXPECT_TRUE(mov->dst.equals(vgrf0));
203 EXPECT_TRUE(mov->src[0].equals(vgrf1));
204
205 EXPECT_EQ(BRW_OPCODE_SEL, sel->opcode);
206 EXPECT_EQ(test[i].conditional_mod, sel->conditional_mod);
207 EXPECT_EQ(test[i].expected_result, sel->saturate);
208 EXPECT_TRUE(sel->dst.equals(vgrf2));
209 if (test[i].expected_result) {
210 EXPECT_TRUE(sel->src[0].equals(vgrf1));
211 } else {
212 EXPECT_TRUE(sel->src[0].equals(vgrf0));
213 }
214 EXPECT_TRUE(sel->src[1].equals(brw_imm_f(test[i].immediate)));
215
216 delete v->cfg;
217 v->cfg = NULL;
218 }
219 }
220
TEST_F(copy_propagation_test,mixed_integer_sign)221 TEST_F(copy_propagation_test, mixed_integer_sign)
222 {
223 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_UD);
224 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_D);
225 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_UD);
226 brw_reg vgrf3 = bld.vgrf(BRW_TYPE_UD);
227 brw_reg vgrf4 = bld.vgrf(BRW_TYPE_UD);
228
229 bld.MOV(vgrf1, vgrf0);
230 bld.BFE(vgrf2, vgrf3, vgrf4, retype(vgrf1, BRW_TYPE_UD));
231
232 /* = Before =
233 *
234 * 0: mov(8) vgrf1:D vgrf0:UD
235 * 1: bfe(8) vgrf2:UD vgrf3:UD vgrf4:UD vgrf1:UD
236 *
237 * = After =
238 * 0: mov(8) vgrf1:D vgrf0:UD
239 * 1: bfe(8) vgrf2:UD vgrf3:UD vgrf4:UD vgrf0:UD
240 */
241
242 brw_calculate_cfg(*v);
243 bblock_t *block0 = v->cfg->blocks[0];
244
245 EXPECT_EQ(0, block0->start_ip);
246 EXPECT_EQ(1, block0->end_ip);
247
248 EXPECT_TRUE(copy_propagation(v));
249 EXPECT_EQ(0, block0->start_ip);
250 EXPECT_EQ(1, block0->end_ip);
251
252 fs_inst *mov = instruction(block0, 0);
253 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
254 EXPECT_TRUE(mov->dst.equals(vgrf1));
255 EXPECT_TRUE(mov->src[0].equals(vgrf0));
256
257 fs_inst *bfe = instruction(block0, 1);
258 EXPECT_EQ(BRW_OPCODE_BFE, bfe->opcode);
259 EXPECT_TRUE(bfe->dst.equals(vgrf2));
260 EXPECT_TRUE(bfe->src[0].equals(vgrf3));
261 EXPECT_TRUE(bfe->src[1].equals(vgrf4));
262 EXPECT_TRUE(bfe->src[2].equals(vgrf0));
263 }
264
TEST_F(copy_propagation_test,mixed_integer_sign_with_vector_imm)265 TEST_F(copy_propagation_test, mixed_integer_sign_with_vector_imm)
266 {
267 brw_reg vgrf0 = bld.vgrf(BRW_TYPE_W);
268 brw_reg vgrf1 = bld.vgrf(BRW_TYPE_UD);
269 brw_reg vgrf2 = bld.vgrf(BRW_TYPE_UD);
270
271 bld.MOV(vgrf0, brw_imm_uv(0xffff));
272 bld.ADD(vgrf1, vgrf2, retype(vgrf0, BRW_TYPE_UW));
273
274 /* = Before =
275 *
276 * 0: mov(8) vgrf0:W ...:UV
277 * 1: add(8) vgrf1:UD vgrf2:UD vgrf0:UW
278 *
279 * = After =
280 * No change
281 */
282
283 brw_calculate_cfg(*v);
284 bblock_t *block0 = v->cfg->blocks[0];
285
286 const brw_reg src1 = instruction(block0, 1)->src[1];
287
288 EXPECT_EQ(0, block0->start_ip);
289 EXPECT_EQ(1, block0->end_ip);
290
291 EXPECT_FALSE(copy_propagation(v));
292 EXPECT_EQ(0, block0->start_ip);
293 EXPECT_EQ(1, block0->end_ip);
294
295 fs_inst *mov = instruction(block0, 0);
296 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
297 EXPECT_TRUE(mov->dst.equals(vgrf0));
298 EXPECT_TRUE(mov->src[0].file == IMM);
299
300 fs_inst *add = instruction(block0, 1);
301 EXPECT_EQ(BRW_OPCODE_ADD, add->opcode);
302 EXPECT_TRUE(add->dst.equals(vgrf1));
303 EXPECT_TRUE(add->src[0].equals(vgrf2));
304 EXPECT_TRUE(add->src[1].equals(src1));
305 }
306