1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <gtest/gtest.h> 25bf215546Sopenharmony_ci#include "brw_fs.h" 26bf215546Sopenharmony_ci#include "brw_cfg.h" 27bf215546Sopenharmony_ci#include "program/program.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ciusing namespace brw; 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ciclass copy_propagation_test : public ::testing::Test { 32bf215546Sopenharmony_ci virtual void SetUp(); 33bf215546Sopenharmony_ci virtual void TearDown(); 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cipublic: 36bf215546Sopenharmony_ci struct brw_compiler *compiler; 37bf215546Sopenharmony_ci struct intel_device_info *devinfo; 38bf215546Sopenharmony_ci void *ctx; 39bf215546Sopenharmony_ci struct brw_wm_prog_data *prog_data; 40bf215546Sopenharmony_ci struct gl_shader_program *shader_prog; 41bf215546Sopenharmony_ci fs_visitor *v; 42bf215546Sopenharmony_ci}; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ciclass copy_propagation_fs_visitor : public fs_visitor 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_cipublic: 47bf215546Sopenharmony_ci copy_propagation_fs_visitor(struct brw_compiler *compiler, 48bf215546Sopenharmony_ci void *mem_ctx, 49bf215546Sopenharmony_ci struct brw_wm_prog_data *prog_data, 50bf215546Sopenharmony_ci nir_shader *shader) 51bf215546Sopenharmony_ci : fs_visitor(compiler, NULL, mem_ctx, NULL, 52bf215546Sopenharmony_ci &prog_data->base, shader, 8, false) {} 53bf215546Sopenharmony_ci}; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_civoid copy_propagation_test::SetUp() 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci ctx = ralloc_context(NULL); 59bf215546Sopenharmony_ci compiler = rzalloc(ctx, struct brw_compiler); 60bf215546Sopenharmony_ci devinfo = rzalloc(ctx, struct intel_device_info); 61bf215546Sopenharmony_ci compiler->devinfo = devinfo; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci prog_data = ralloc(ctx, struct brw_wm_prog_data); 64bf215546Sopenharmony_ci nir_shader *shader = 65bf215546Sopenharmony_ci nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci v = new copy_propagation_fs_visitor(compiler, ctx, prog_data, shader); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci devinfo->ver = 4; 70bf215546Sopenharmony_ci devinfo->verx10 = devinfo->ver * 10; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_civoid copy_propagation_test::TearDown() 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci delete v; 76bf215546Sopenharmony_ci v = NULL; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci ralloc_free(ctx); 79bf215546Sopenharmony_ci ctx = NULL; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistatic fs_inst * 83bf215546Sopenharmony_ciinstruction(bblock_t *block, int num) 84bf215546Sopenharmony_ci{ 85bf215546Sopenharmony_ci fs_inst *inst = (fs_inst *)block->start(); 86bf215546Sopenharmony_ci for (int i = 0; i < num; i++) { 87bf215546Sopenharmony_ci inst = (fs_inst *)inst->next; 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci return inst; 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_cistatic bool 93bf215546Sopenharmony_cicopy_propagation(fs_visitor *v) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci const bool print = getenv("TEST_DEBUG"); 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (print) { 98bf215546Sopenharmony_ci fprintf(stderr, "= Before =\n"); 99bf215546Sopenharmony_ci v->cfg->dump(); 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci bool ret = v->opt_copy_propagation(); 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci if (print) { 105bf215546Sopenharmony_ci fprintf(stderr, "\n= After =\n"); 106bf215546Sopenharmony_ci v->cfg->dump(); 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci return ret; 110bf215546Sopenharmony_ci} 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ciTEST_F(copy_propagation_test, basic) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci const fs_builder &bld = v->bld; 115bf215546Sopenharmony_ci fs_reg vgrf0 = v->vgrf(glsl_type::float_type); 116bf215546Sopenharmony_ci fs_reg vgrf1 = v->vgrf(glsl_type::float_type); 117bf215546Sopenharmony_ci fs_reg vgrf2 = v->vgrf(glsl_type::float_type); 118bf215546Sopenharmony_ci fs_reg vgrf3 = v->vgrf(glsl_type::float_type); 119bf215546Sopenharmony_ci bld.MOV(vgrf0, vgrf2); 120bf215546Sopenharmony_ci bld.ADD(vgrf1, vgrf0, vgrf3); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* = Before = 123bf215546Sopenharmony_ci * 124bf215546Sopenharmony_ci * 0: mov(8) vgrf0 vgrf2 125bf215546Sopenharmony_ci * 1: add(8) vgrf1 vgrf0 vgrf3 126bf215546Sopenharmony_ci * 127bf215546Sopenharmony_ci * = After = 128bf215546Sopenharmony_ci * 0: mov(8) vgrf0 vgrf2 129bf215546Sopenharmony_ci * 1: add(8) vgrf1 vgrf2 vgrf3 130bf215546Sopenharmony_ci */ 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci v->calculate_cfg(); 133bf215546Sopenharmony_ci bblock_t *block0 = v->cfg->blocks[0]; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci EXPECT_EQ(0, block0->start_ip); 136bf215546Sopenharmony_ci EXPECT_EQ(1, block0->end_ip); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci EXPECT_TRUE(copy_propagation(v)); 139bf215546Sopenharmony_ci EXPECT_EQ(0, block0->start_ip); 140bf215546Sopenharmony_ci EXPECT_EQ(1, block0->end_ip); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci fs_inst *mov = instruction(block0, 0); 143bf215546Sopenharmony_ci EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode); 144bf215546Sopenharmony_ci EXPECT_TRUE(mov->dst.equals(vgrf0)); 145bf215546Sopenharmony_ci EXPECT_TRUE(mov->src[0].equals(vgrf2)); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci fs_inst *add = instruction(block0, 1); 148bf215546Sopenharmony_ci EXPECT_EQ(BRW_OPCODE_ADD, add->opcode); 149bf215546Sopenharmony_ci EXPECT_TRUE(add->dst.equals(vgrf1)); 150bf215546Sopenharmony_ci EXPECT_TRUE(add->src[0].equals(vgrf2)); 151bf215546Sopenharmony_ci EXPECT_TRUE(add->src[1].equals(vgrf3)); 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ciTEST_F(copy_propagation_test, maxmax_sat_imm) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci const fs_builder &bld = v->bld; 157bf215546Sopenharmony_ci fs_reg vgrf0 = v->vgrf(glsl_type::float_type); 158bf215546Sopenharmony_ci fs_reg vgrf1 = v->vgrf(glsl_type::float_type); 159bf215546Sopenharmony_ci fs_reg vgrf2 = v->vgrf(glsl_type::float_type); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci static const struct { 162bf215546Sopenharmony_ci enum brw_conditional_mod conditional_mod; 163bf215546Sopenharmony_ci float immediate; 164bf215546Sopenharmony_ci bool expected_result; 165bf215546Sopenharmony_ci } test[] = { 166bf215546Sopenharmony_ci /* conditional mod, imm, expected_result */ 167bf215546Sopenharmony_ci { BRW_CONDITIONAL_GE , 0.1f, true }, 168bf215546Sopenharmony_ci { BRW_CONDITIONAL_L , 0.1f, true }, 169bf215546Sopenharmony_ci { BRW_CONDITIONAL_GE , 0.5f, true }, 170bf215546Sopenharmony_ci { BRW_CONDITIONAL_L , 0.5f, true }, 171bf215546Sopenharmony_ci { BRW_CONDITIONAL_GE , 0.9f, true }, 172bf215546Sopenharmony_ci { BRW_CONDITIONAL_L , 0.9f, true }, 173bf215546Sopenharmony_ci { BRW_CONDITIONAL_GE , -1.5f, false }, 174bf215546Sopenharmony_ci { BRW_CONDITIONAL_L , -1.5f, false }, 175bf215546Sopenharmony_ci { BRW_CONDITIONAL_GE , 1.5f, false }, 176bf215546Sopenharmony_ci { BRW_CONDITIONAL_L , 1.5f, false }, 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci { BRW_CONDITIONAL_NONE, 0.5f, false }, 179bf215546Sopenharmony_ci { BRW_CONDITIONAL_Z , 0.5f, false }, 180bf215546Sopenharmony_ci { BRW_CONDITIONAL_NZ , 0.5f, false }, 181bf215546Sopenharmony_ci { BRW_CONDITIONAL_G , 0.5f, false }, 182bf215546Sopenharmony_ci { BRW_CONDITIONAL_LE , 0.5f, false }, 183bf215546Sopenharmony_ci { BRW_CONDITIONAL_R , 0.5f, false }, 184bf215546Sopenharmony_ci { BRW_CONDITIONAL_O , 0.5f, false }, 185bf215546Sopenharmony_ci { BRW_CONDITIONAL_U , 0.5f, false }, 186bf215546Sopenharmony_ci }; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci for (unsigned i = 0; i < sizeof(test) / sizeof(test[0]); i++) { 189bf215546Sopenharmony_ci fs_inst *mov = set_saturate(true, bld.MOV(vgrf0, vgrf1)); 190bf215546Sopenharmony_ci fs_inst *sel = set_condmod(test[i].conditional_mod, 191bf215546Sopenharmony_ci bld.SEL(vgrf2, vgrf0, 192bf215546Sopenharmony_ci brw_imm_f(test[i].immediate))); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci v->calculate_cfg(); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci bblock_t *block0 = v->cfg->blocks[0]; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci EXPECT_EQ(0, block0->start_ip); 199bf215546Sopenharmony_ci EXPECT_EQ(1, block0->end_ip); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci EXPECT_EQ(test[i].expected_result, copy_propagation(v)); 202bf215546Sopenharmony_ci EXPECT_EQ(0, block0->start_ip); 203bf215546Sopenharmony_ci EXPECT_EQ(1, block0->end_ip); 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci EXPECT_EQ(BRW_OPCODE_MOV, mov->opcode); 206bf215546Sopenharmony_ci EXPECT_TRUE(mov->saturate); 207bf215546Sopenharmony_ci EXPECT_TRUE(mov->dst.equals(vgrf0)); 208bf215546Sopenharmony_ci EXPECT_TRUE(mov->src[0].equals(vgrf1)); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci EXPECT_EQ(BRW_OPCODE_SEL, sel->opcode); 211bf215546Sopenharmony_ci EXPECT_EQ(test[i].conditional_mod, sel->conditional_mod); 212bf215546Sopenharmony_ci EXPECT_EQ(test[i].expected_result, sel->saturate); 213bf215546Sopenharmony_ci EXPECT_TRUE(sel->dst.equals(vgrf2)); 214bf215546Sopenharmony_ci if (test[i].expected_result) { 215bf215546Sopenharmony_ci EXPECT_TRUE(sel->src[0].equals(vgrf1)); 216bf215546Sopenharmony_ci } else { 217bf215546Sopenharmony_ci EXPECT_TRUE(sel->src[0].equals(vgrf0)); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci EXPECT_TRUE(sel->src[1].equals(brw_imm_f(test[i].immediate))); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci delete v->cfg; 222bf215546Sopenharmony_ci v->cfg = NULL; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci} 225