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