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 "elk_fs.h"
26 #include "elk_fs_builder.h"
27 #include "elk_cfg.h"
28
29 using namespace elk;
30
31 class copy_propagation_test : public ::testing::Test {
32 protected:
33 copy_propagation_test();
34 ~copy_propagation_test() override;
35
36 struct elk_compiler *compiler;
37 struct elk_compile_params params;
38 struct intel_device_info *devinfo;
39 void *ctx;
40 struct elk_wm_prog_data *prog_data;
41 struct gl_shader_program *shader_prog;
42 elk_fs_visitor *v;
43 fs_builder bld;
44 };
45
46 class copy_propagation_fs_visitor : public elk_fs_visitor
47 {
48 public:
copy_propagation_fs_visitor(struct elk_compiler * compiler,struct elk_compile_params * params,struct elk_wm_prog_data * prog_data,nir_shader * shader)49 copy_propagation_fs_visitor(struct elk_compiler *compiler,
50 struct elk_compile_params *params,
51 struct elk_wm_prog_data *prog_data,
52 nir_shader *shader)
53 : elk_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 elk_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 elk_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 = 4;
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 elk_fs_inst *
instruction(elk_bblock_t * block,int num)91 instruction(elk_bblock_t *block, int num)
92 {
93 elk_fs_inst *inst = (elk_fs_inst *)block->start();
94 for (int i = 0; i < num; i++) {
95 inst = (elk_fs_inst *)inst->next;
96 }
97 return inst;
98 }
99
100 static bool
copy_propagation(elk_fs_visitor * v)101 copy_propagation(elk_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 = v->opt_copy_propagation();
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 elk_fs_reg vgrf0 = v->vgrf(glsl_float_type());
123 elk_fs_reg vgrf1 = v->vgrf(glsl_float_type());
124 elk_fs_reg vgrf2 = v->vgrf(glsl_float_type());
125 elk_fs_reg vgrf3 = v->vgrf(glsl_float_type());
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 v->calculate_cfg();
140 elk_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 elk_fs_inst *mov = instruction(block0, 0);
150 EXPECT_EQ(ELK_OPCODE_MOV, mov->opcode);
151 EXPECT_TRUE(mov->dst.equals(vgrf0));
152 EXPECT_TRUE(mov->src[0].equals(vgrf2));
153
154 elk_fs_inst *add = instruction(block0, 1);
155 EXPECT_EQ(ELK_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 elk_fs_reg vgrf0 = v->vgrf(glsl_float_type());
164 elk_fs_reg vgrf1 = v->vgrf(glsl_float_type());
165 elk_fs_reg vgrf2 = v->vgrf(glsl_float_type());
166
167 static const struct {
168 enum elk_conditional_mod conditional_mod;
169 float immediate;
170 bool expected_result;
171 } test[] = {
172 /* conditional mod, imm, expected_result */
173 { ELK_CONDITIONAL_GE , 0.1f, false },
174 { ELK_CONDITIONAL_L , 0.1f, false },
175 { ELK_CONDITIONAL_GE , 0.5f, false },
176 { ELK_CONDITIONAL_L , 0.5f, false },
177 { ELK_CONDITIONAL_GE , 0.9f, false },
178 { ELK_CONDITIONAL_L , 0.9f, false },
179 { ELK_CONDITIONAL_GE , -1.5f, false },
180 { ELK_CONDITIONAL_L , -1.5f, false },
181 { ELK_CONDITIONAL_GE , 1.5f, false },
182 { ELK_CONDITIONAL_L , 1.5f, false },
183
184 { ELK_CONDITIONAL_NONE, 0.5f, false },
185 { ELK_CONDITIONAL_Z , 0.5f, false },
186 { ELK_CONDITIONAL_NZ , 0.5f, false },
187 { ELK_CONDITIONAL_G , 0.5f, false },
188 { ELK_CONDITIONAL_LE , 0.5f, false },
189 { ELK_CONDITIONAL_R , 0.5f, false },
190 { ELK_CONDITIONAL_O , 0.5f, false },
191 { ELK_CONDITIONAL_U , 0.5f, false },
192 };
193
194 for (unsigned i = 0; i < sizeof(test) / sizeof(test[0]); i++) {
195 elk_fs_inst *mov = set_saturate(true, bld.MOV(vgrf0, vgrf1));
196 elk_fs_inst *sel = set_condmod(test[i].conditional_mod,
197 bld.SEL(vgrf2, vgrf0,
198 elk_imm_f(test[i].immediate)));
199
200 v->calculate_cfg();
201
202 elk_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(ELK_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(ELK_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(elk_imm_f(test[i].immediate)));
226
227 delete v->cfg;
228 v->cfg = NULL;
229 }
230 }
231