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 29using namespace brw; 30 31class copy_propagation_test : public ::testing::Test { 32 virtual void SetUp(); 33 virtual void TearDown(); 34 35public: 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 44class copy_propagation_fs_visitor : public fs_visitor 45{ 46public: 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, false) {} 53}; 54 55 56void 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 73void copy_propagation_test::TearDown() 74{ 75 delete v; 76 v = NULL; 77 78 ralloc_free(ctx); 79 ctx = NULL; 80} 81 82static fs_inst * 83instruction(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 92static bool 93copy_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 112TEST_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 154TEST_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