1/* 2 * Copyright © 2012 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_vec4.h" 26#include "program/program.h" 27 28using namespace brw; 29 30int ret = 0; 31 32#define register_coalesce(v) _register_coalesce(v, __func__) 33 34class register_coalesce_test : public ::testing::Test { 35 virtual void SetUp(); 36 37public: 38 struct brw_compiler *compiler; 39 struct gen_device_info *devinfo; 40 struct gl_context *ctx; 41 struct gl_shader_program *shader_prog; 42 struct brw_vue_prog_data *prog_data; 43 vec4_visitor *v; 44}; 45 46 47class register_coalesce_vec4_visitor : public vec4_visitor 48{ 49public: 50 register_coalesce_vec4_visitor(struct brw_compiler *compiler, 51 nir_shader *shader, 52 struct brw_vue_prog_data *prog_data) 53 : vec4_visitor(compiler, NULL, NULL, prog_data, shader, NULL, 54 false /* no_spills */, -1) 55 { 56 prog_data->dispatch_mode = DISPATCH_MODE_4X2_DUAL_OBJECT; 57 } 58 59protected: 60 virtual dst_reg *make_reg_for_system_value(int /* location */) 61 { 62 unreachable("Not reached"); 63 } 64 65 virtual void setup_payload() 66 { 67 unreachable("Not reached"); 68 } 69 70 virtual void emit_prolog() 71 { 72 unreachable("Not reached"); 73 } 74 75 virtual void emit_thread_end() 76 { 77 unreachable("Not reached"); 78 } 79 80 virtual void emit_urb_write_header(int /* mrf */) 81 { 82 unreachable("Not reached"); 83 } 84 85 virtual vec4_instruction *emit_urb_write_opcode(bool /* complete */) 86 { 87 unreachable("Not reached"); 88 } 89}; 90 91 92void register_coalesce_test::SetUp() 93{ 94 ctx = (struct gl_context *)calloc(1, sizeof(*ctx)); 95 compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler)); 96 devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo)); 97 prog_data = (struct brw_vue_prog_data *)calloc(1, sizeof(*prog_data)); 98 compiler->devinfo = devinfo; 99 100 nir_shader *shader = 101 nir_shader_create(NULL, MESA_SHADER_VERTEX, NULL, NULL); 102 103 v = new register_coalesce_vec4_visitor(compiler, shader, prog_data); 104 105 devinfo->gen = 4; 106} 107 108static void 109_register_coalesce(vec4_visitor *v, const char *func) 110{ 111 bool print = false; 112 113 if (print) { 114 printf("%s: instructions before:\n", func); 115 v->dump_instructions(); 116 } 117 118 v->calculate_cfg(); 119 v->opt_register_coalesce(); 120 121 if (print) { 122 printf("%s: instructions after:\n", func); 123 v->dump_instructions(); 124 } 125} 126 127TEST_F(register_coalesce_test, test_compute_to_mrf) 128{ 129 src_reg something = src_reg(v, glsl_type::float_type); 130 dst_reg temp = dst_reg(v, glsl_type::float_type); 131 dst_reg init; 132 133 dst_reg m0 = dst_reg(MRF, 0); 134 m0.writemask = WRITEMASK_X; 135 m0.type = BRW_REGISTER_TYPE_F; 136 137 vec4_instruction *mul = v->emit(v->MUL(temp, something, brw_imm_f(1.0f))); 138 v->emit(v->MOV(m0, src_reg(temp))); 139 140 register_coalesce(v); 141 142 EXPECT_EQ(mul->dst.file, MRF); 143} 144 145 146TEST_F(register_coalesce_test, test_multiple_use) 147{ 148 src_reg something = src_reg(v, glsl_type::float_type); 149 dst_reg temp = dst_reg(v, glsl_type::vec4_type); 150 dst_reg init; 151 152 dst_reg m0 = dst_reg(MRF, 0); 153 m0.writemask = WRITEMASK_X; 154 m0.type = BRW_REGISTER_TYPE_F; 155 156 dst_reg m1 = dst_reg(MRF, 1); 157 m1.writemask = WRITEMASK_XYZW; 158 m1.type = BRW_REGISTER_TYPE_F; 159 160 src_reg src = src_reg(temp); 161 vec4_instruction *mul = v->emit(v->MUL(temp, something, brw_imm_f(1.0f))); 162 src.swizzle = BRW_SWIZZLE_XXXX; 163 v->emit(v->MOV(m0, src)); 164 src.swizzle = BRW_SWIZZLE_XYZW; 165 v->emit(v->MOV(m1, src)); 166 167 register_coalesce(v); 168 169 EXPECT_NE(mul->dst.file, MRF); 170} 171 172TEST_F(register_coalesce_test, test_dp4_mrf) 173{ 174 src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); 175 src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); 176 dst_reg init; 177 178 dst_reg m0 = dst_reg(MRF, 0); 179 m0.writemask = WRITEMASK_Y; 180 m0.type = BRW_REGISTER_TYPE_F; 181 182 dst_reg temp = dst_reg(v, glsl_type::float_type); 183 184 vec4_instruction *dp4 = v->emit(v->DP4(temp, some_src_1, some_src_2)); 185 v->emit(v->MOV(m0, src_reg(temp))); 186 187 register_coalesce(v); 188 189 EXPECT_EQ(dp4->dst.file, MRF); 190 EXPECT_EQ(dp4->dst.writemask, WRITEMASK_Y); 191} 192 193TEST_F(register_coalesce_test, test_dp4_grf) 194{ 195 src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); 196 src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); 197 dst_reg init; 198 199 dst_reg to = dst_reg(v, glsl_type::vec4_type); 200 dst_reg temp = dst_reg(v, glsl_type::float_type); 201 202 vec4_instruction *dp4 = v->emit(v->DP4(temp, some_src_1, some_src_2)); 203 to.writemask = WRITEMASK_Y; 204 v->emit(v->MOV(to, src_reg(temp))); 205 206 /* if we don't do something with the result, the automatic dead code 207 * elimination will remove all our instructions. 208 */ 209 src_reg src = src_reg(to); 210 src.negate = true; 211 v->emit(v->MOV(dst_reg(MRF, 0), src)); 212 213 register_coalesce(v); 214 215 EXPECT_EQ(dp4->dst.nr, to.nr); 216 EXPECT_EQ(dp4->dst.writemask, WRITEMASK_Y); 217} 218 219TEST_F(register_coalesce_test, test_channel_mul_grf) 220{ 221 src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); 222 src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); 223 dst_reg init; 224 225 dst_reg to = dst_reg(v, glsl_type::vec4_type); 226 dst_reg temp = dst_reg(v, glsl_type::float_type); 227 228 vec4_instruction *mul = v->emit(v->MUL(temp, some_src_1, some_src_2)); 229 to.writemask = WRITEMASK_Y; 230 v->emit(v->MOV(to, src_reg(temp))); 231 232 /* if we don't do something with the result, the automatic dead code 233 * elimination will remove all our instructions. 234 */ 235 src_reg src = src_reg(to); 236 src.negate = true; 237 v->emit(v->MOV(dst_reg(MRF, 0), src)); 238 239 register_coalesce(v); 240 241 EXPECT_EQ(mul->dst.nr, to.nr); 242} 243