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_cfg.h"
27 #include "program/program.h"
28
29 using namespace brw;
30
31 class copy_propagation_test : public ::testing::Test {
32 virtual void SetUp();
33 virtual void TearDown();
34
35 public:
36 struct brw_compiler *compiler;
37 struct intel_device_info *devinfo;
38 void *ctx;
39 struct brw_wm_prog_data *prog_data;
40 struct gl_shader_program *shader_prog;
41 fs_visitor *v;
42 };
43
44 class copy_propagation_fs_visitor : public fs_visitor
45 {
46 public:
copy_propagation_fs_visitor(struct brw_compiler * compiler,void * mem_ctx,struct brw_wm_prog_data * prog_data,nir_shader * shader)47 copy_propagation_fs_visitor(struct brw_compiler *compiler,
48 void *mem_ctx,
49 struct brw_wm_prog_data *prog_data,
50 nir_shader *shader)
51 : fs_visitor(compiler, NULL, mem_ctx, NULL,
52 &prog_data->base, shader, 8, -1, false) {}
53 };
54
55
SetUp()56 void copy_propagation_test::SetUp()
57 {
58 ctx = ralloc_context(NULL);
59 compiler = rzalloc(ctx, struct brw_compiler);
60 devinfo = rzalloc(ctx, struct intel_device_info);
61 compiler->devinfo = devinfo;
62
63 prog_data = ralloc(ctx, struct brw_wm_prog_data);
64 nir_shader *shader =
65 nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
66
67 v = new copy_propagation_fs_visitor(compiler, ctx, prog_data, shader);
68
69 devinfo->ver = 4;
70 devinfo->verx10 = devinfo->ver * 10;
71 }
72
TearDown()73 void copy_propagation_test::TearDown()
74 {
75 delete v;
76 v = NULL;
77
78 ralloc_free(ctx);
79 ctx = NULL;
80 }
81
82 static fs_inst *
instruction(bblock_t * block,int num)83 instruction(bblock_t *block, int num)
84 {
85 fs_inst *inst = (fs_inst *)block->start();
86 for (int i = 0; i < num; i++) {
87 inst = (fs_inst *)inst->next;
88 }
89 return inst;
90 }
91
92 static bool
copy_propagation(fs_visitor * v)93 copy_propagation(fs_visitor *v)
94 {
95 const bool print = getenv("TEST_DEBUG");
96
97 if (print) {
98 fprintf(stderr, "= Before =\n");
99 v->cfg->dump();
100 }
101
102 bool ret = v->opt_copy_propagation();
103
104 if (print) {
105 fprintf(stderr, "\n= After =\n");
106 v->cfg->dump();
107 }
108
109 return ret;
110 }
111
TEST_F(copy_propagation_test,basic)112 TEST_F(copy_propagation_test, basic)
113 {
114 const fs_builder &bld = v->bld;
115 fs_reg vgrf0 = v->vgrf(glsl_type::float_type);
116 fs_reg vgrf1 = v->vgrf(glsl_type::float_type);
117 fs_reg vgrf2 = v->vgrf(glsl_type::float_type);
118 fs_reg vgrf3 = v->vgrf(glsl_type::float_type);
119 bld.MOV(vgrf0, vgrf2);
120 bld.ADD(vgrf1, vgrf0, vgrf3);
121
122 /* = Before =
123 *
124 * 0: mov(8) vgrf0 vgrf2
125 * 1: add(8) vgrf1 vgrf0 vgrf3
126 *
127 * = After =
128 * 0: mov(8) vgrf0 vgrf2
129 * 1: add(8) vgrf1 vgrf2 vgrf3
130 */
131
132 v->calculate_cfg();
133 bblock_t *block0 = v->cfg->blocks[0];
134
135 EXPECT_EQ(0, block0->start_ip);
136 EXPECT_EQ(1, block0->end_ip);
137
138 EXPECT_TRUE(copy_propagation(v));
139 EXPECT_EQ(0, block0->start_ip);
140 EXPECT_EQ(1, block0->end_ip);
141
142 fs_inst *mov = instruction(block0, 0);
143 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
144 EXPECT_TRUE(mov->dst.equals(vgrf0));
145 EXPECT_TRUE(mov->src[0].equals(vgrf2));
146
147 fs_inst *add = instruction(block0, 1);
148 EXPECT_EQ(BRW_OPCODE_ADD, add->opcode);
149 EXPECT_TRUE(add->dst.equals(vgrf1));
150 EXPECT_TRUE(add->src[0].equals(vgrf2));
151 EXPECT_TRUE(add->src[1].equals(vgrf3));
152 }
153
TEST_F(copy_propagation_test,maxmax_sat_imm)154 TEST_F(copy_propagation_test, maxmax_sat_imm)
155 {
156 const fs_builder &bld = v->bld;
157 fs_reg vgrf0 = v->vgrf(glsl_type::float_type);
158 fs_reg vgrf1 = v->vgrf(glsl_type::float_type);
159 fs_reg vgrf2 = v->vgrf(glsl_type::float_type);
160
161 static const struct {
162 enum brw_conditional_mod conditional_mod;
163 float immediate;
164 bool expected_result;
165 } test[] = {
166 /* conditional mod, imm, expected_result */
167 { BRW_CONDITIONAL_GE , 0.1f, true },
168 { BRW_CONDITIONAL_L , 0.1f, true },
169 { BRW_CONDITIONAL_GE , 0.5f, true },
170 { BRW_CONDITIONAL_L , 0.5f, true },
171 { BRW_CONDITIONAL_GE , 0.9f, true },
172 { BRW_CONDITIONAL_L , 0.9f, true },
173 { BRW_CONDITIONAL_GE , -1.5f, false },
174 { BRW_CONDITIONAL_L , -1.5f, false },
175 { BRW_CONDITIONAL_GE , 1.5f, false },
176 { BRW_CONDITIONAL_L , 1.5f, false },
177
178 { BRW_CONDITIONAL_NONE, 0.5f, false },
179 { BRW_CONDITIONAL_Z , 0.5f, false },
180 { BRW_CONDITIONAL_NZ , 0.5f, false },
181 { BRW_CONDITIONAL_G , 0.5f, false },
182 { BRW_CONDITIONAL_LE , 0.5f, false },
183 { BRW_CONDITIONAL_R , 0.5f, false },
184 { BRW_CONDITIONAL_O , 0.5f, false },
185 { BRW_CONDITIONAL_U , 0.5f, false },
186 };
187
188 for (unsigned i = 0; i < sizeof(test) / sizeof(test[0]); i++) {
189 fs_inst *mov = set_saturate(true, bld.MOV(vgrf0, vgrf1));
190 fs_inst *sel = set_condmod(test[i].conditional_mod,
191 bld.SEL(vgrf2, vgrf0,
192 brw_imm_f(test[i].immediate)));
193
194 v->calculate_cfg();
195
196 bblock_t *block0 = v->cfg->blocks[0];
197
198 EXPECT_EQ(0, block0->start_ip);
199 EXPECT_EQ(1, block0->end_ip);
200
201 EXPECT_EQ(test[i].expected_result, copy_propagation(v));
202 EXPECT_EQ(0, block0->start_ip);
203 EXPECT_EQ(1, block0->end_ip);
204
205 EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode);
206 EXPECT_TRUE(mov->saturate);
207 EXPECT_TRUE(mov->dst.equals(vgrf0));
208 EXPECT_TRUE(mov->src[0].equals(vgrf1));
209
210 EXPECT_EQ(BRW_OPCODE_SEL, sel->opcode);
211 EXPECT_EQ(test[i].conditional_mod, sel->conditional_mod);
212 EXPECT_EQ(test[i].expected_result, sel->saturate);
213 EXPECT_TRUE(sel->dst.equals(vgrf2));
214 if (test[i].expected_result) {
215 EXPECT_TRUE(sel->src[0].equals(vgrf1));
216 } else {
217 EXPECT_TRUE(sel->src[0].equals(vgrf0));
218 }
219 EXPECT_TRUE(sel->src[1].equals(brw_imm_f(test[i].immediate)));
220
221 delete v->cfg;
222 v->cfg = NULL;
223 }
224 }
225