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