Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright  2013 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
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 #include <gtest/gtest.h>
     24 #include "main/compiler.h"
     25 #include "main/mtypes.h"
     26 #include "main/macros.h"
     27 #include "ir.h"
     28 #include "ir_builder.h"
     29 
     30 using namespace ir_builder;
     31 
     32 namespace lower_64bit {
     33 void expand_source(ir_factory &body,
     34                    ir_rvalue *val,
     35                    ir_variable **expanded_src);
     36 
     37 ir_dereference_variable *compact_destination(ir_factory &body,
     38                                              const glsl_type *type,
     39                                              ir_variable *result[4]);
     40 
     41 ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir,
     42                                      ir_expression *ir,
     43                                      ir_function_signature *callee);
     44 };
     45 
     46 class expand_source : public ::testing::Test {
     47 public:
     48    virtual void SetUp();
     49    virtual void TearDown();
     50 
     51    exec_list instructions;
     52    ir_factory *body;
     53    ir_variable *expanded_src[4];
     54    void *mem_ctx;
     55 };
     56 
     57 void
     58 expand_source::SetUp()
     59 {
     60    mem_ctx = ralloc_context(NULL);
     61 
     62    memset(expanded_src, 0, sizeof(expanded_src));
     63    instructions.make_empty();
     64    body = new ir_factory(&instructions, mem_ctx);
     65 }
     66 
     67 void
     68 expand_source::TearDown()
     69 {
     70    delete body;
     71    body = NULL;
     72 
     73    ralloc_free(mem_ctx);
     74    mem_ctx = NULL;
     75 }
     76 
     77 static ir_dereference_variable *
     78 create_variable(void *mem_ctx, const glsl_type *type)
     79 {
     80    ir_variable *var = new(mem_ctx) ir_variable(type,
     81                                                "variable",
     82                                                ir_var_temporary);
     83 
     84    return new(mem_ctx) ir_dereference_variable(var);
     85 }
     86 
     87 static ir_expression *
     88 create_expression(void *mem_ctx, const glsl_type *type)
     89 {
     90    return new(mem_ctx) ir_expression(ir_unop_neg,
     91                                      create_variable(mem_ctx, type));
     92 }
     93 
     94 static void
     95 check_expanded_source(const glsl_type *type,
     96                       ir_variable *expanded_src[4])
     97 {
     98    const glsl_type *const expanded_type =
     99       type->base_type == GLSL_TYPE_UINT64
    100       ? glsl_type::uvec2_type :glsl_type::ivec2_type;
    101 
    102    for (int i = 0; i < type->vector_elements; i++) {
    103       EXPECT_EQ(expanded_type, expanded_src[i]->type);
    104 
    105       /* All elements that are part of the vector must be unique. */
    106       for (int j = i - 1; j >= 0; j--) {
    107          EXPECT_NE(expanded_src[i], expanded_src[j])
    108             << "    Element " << i << " is the same as element " << j;
    109       }
    110    }
    111 
    112    /* All elements that are not part of the vector must be the same as element
    113     * 0.  This is primarily for scalars (where every element is the same).
    114     */
    115    for (int i = type->vector_elements; i < 4; i++) {
    116       EXPECT_EQ(expanded_src[0], expanded_src[i])
    117          << "    Element " << i << " should be the same as element 0";
    118    }
    119 }
    120 
    121 static void
    122 check_instructions(exec_list *instructions,
    123                    const glsl_type *type,
    124                    const ir_instruction *source)
    125 {
    126    const glsl_type *const expanded_type =
    127       type->base_type == GLSL_TYPE_UINT64
    128       ? glsl_type::uvec2_type : glsl_type::ivec2_type;
    129 
    130    const ir_expression_operation unpack_opcode =
    131       type->base_type == GLSL_TYPE_UINT64
    132       ? ir_unop_unpack_uint_2x32 : ir_unop_unpack_int_2x32;
    133 
    134    ir_instruction *ir;
    135 
    136    /* The instruction list should contain IR to represent:
    137     *
    138     *    type tmp1;
    139     *    tmp1 = source;
    140     *    uvec2 tmp2;
    141     *    tmp2 = unpackUint2x32(tmp1.x);
    142     *    uvec2 tmp3;
    143     *    tmp3 = unpackUint2x32(tmp1.y);
    144     *    uvec2 tmp4;
    145     *    tmp4 = unpackUint2x32(tmp1.z);
    146     *    uvec2 tmp5;
    147     *    tmp5 = unpackUint2x32(tmp1.w);
    148     */
    149    ASSERT_FALSE(instructions->is_empty());
    150    ir = (ir_instruction *) instructions->pop_head();
    151    ir_variable *const tmp1 = ir->as_variable();
    152    EXPECT_EQ(ir_type_variable, ir->ir_type);
    153    EXPECT_EQ(type, tmp1->type) <<
    154       "    Got " <<
    155       tmp1->type->name <<
    156       ", expected " <<
    157       type->name;
    158 
    159    ASSERT_FALSE(instructions->is_empty());
    160    ir = (ir_instruction *) instructions->pop_head();
    161    ir_assignment *const assign1 = ir->as_assignment();
    162    EXPECT_EQ(ir_type_assignment, ir->ir_type);
    163    ASSERT_NE((void *)0, assign1);
    164    EXPECT_EQ(tmp1, assign1->lhs->variable_referenced());
    165    EXPECT_EQ(source, assign1->rhs);
    166 
    167    for (unsigned i = 0; i < type->vector_elements; i++) {
    168       ASSERT_FALSE(instructions->is_empty());
    169       ir = (ir_instruction *) instructions->pop_head();
    170       ir_variable *const tmp2 = ir->as_variable();
    171       EXPECT_EQ(ir_type_variable, ir->ir_type);
    172       EXPECT_EQ(expanded_type, tmp2->type);
    173 
    174       ASSERT_FALSE(instructions->is_empty());
    175       ir = (ir_instruction *) instructions->pop_head();
    176       ir_assignment *const assign2 = ir->as_assignment();
    177       EXPECT_EQ(ir_type_assignment, ir->ir_type);
    178       ASSERT_NE((void *)0, assign2);
    179       EXPECT_EQ(tmp2, assign2->lhs->variable_referenced());
    180       ir_expression *unpack = assign2->rhs->as_expression();
    181       ASSERT_NE((void *)0, unpack);
    182       EXPECT_EQ(unpack_opcode, unpack->operation);
    183       EXPECT_EQ(tmp1, unpack->operands[0]->variable_referenced());
    184    }
    185 
    186    EXPECT_TRUE(instructions->is_empty());
    187 }
    188 
    189 TEST_F(expand_source, uint64_variable)
    190 {
    191    const glsl_type *const type = glsl_type::uint64_t_type;
    192    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    193 
    194    lower_64bit::expand_source(*body, deref, expanded_src);
    195 
    196    check_expanded_source(type, expanded_src);
    197    check_instructions(&instructions, type, deref);
    198 }
    199 
    200 TEST_F(expand_source, u64vec2_variable)
    201 {
    202    const glsl_type *const type = glsl_type::u64vec2_type;
    203    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    204 
    205    lower_64bit::expand_source(*body, deref, expanded_src);
    206 
    207    check_expanded_source(type, expanded_src);
    208    check_instructions(&instructions, type, deref);
    209 }
    210 
    211 TEST_F(expand_source, u64vec3_variable)
    212 {
    213    const glsl_type *const type = glsl_type::u64vec3_type;
    214 
    215    /* Generate an operand that is a scalar variable dereference. */
    216    ir_variable *const var = new(mem_ctx) ir_variable(type,
    217                                                      "variable",
    218                                                      ir_var_temporary);
    219 
    220    ir_dereference_variable *const deref =
    221       new(mem_ctx) ir_dereference_variable(var);
    222 
    223    lower_64bit::expand_source(*body, deref, expanded_src);
    224 
    225    check_expanded_source(type, expanded_src);
    226    check_instructions(&instructions, type, deref);
    227 }
    228 
    229 TEST_F(expand_source, u64vec4_variable)
    230 {
    231    const glsl_type *const type = glsl_type::u64vec4_type;
    232    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    233 
    234    lower_64bit::expand_source(*body, deref, expanded_src);
    235 
    236    check_expanded_source(type, expanded_src);
    237    check_instructions(&instructions, type, deref);
    238 }
    239 
    240 TEST_F(expand_source, int64_variable)
    241 {
    242    const glsl_type *const type = glsl_type::int64_t_type;
    243    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    244 
    245    lower_64bit::expand_source(*body, deref, expanded_src);
    246 
    247    check_expanded_source(type, expanded_src);
    248    check_instructions(&instructions, type, deref);
    249 }
    250 
    251 TEST_F(expand_source, i64vec2_variable)
    252 {
    253    const glsl_type *const type = glsl_type::i64vec2_type;
    254    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    255 
    256    lower_64bit::expand_source(*body, deref, expanded_src);
    257 
    258    check_expanded_source(type, expanded_src);
    259    check_instructions(&instructions, type, deref);
    260 }
    261 
    262 TEST_F(expand_source, i64vec3_variable)
    263 {
    264    const glsl_type *const type = glsl_type::i64vec3_type;
    265    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    266 
    267    lower_64bit::expand_source(*body, deref, expanded_src);
    268 
    269    check_expanded_source(type, expanded_src);
    270    check_instructions(&instructions, type, deref);
    271 }
    272 
    273 TEST_F(expand_source, i64vec4_variable)
    274 {
    275    const glsl_type *const type = glsl_type::i64vec4_type;
    276    ir_dereference_variable *const deref = create_variable(mem_ctx, type);
    277 
    278    lower_64bit::expand_source(*body, deref, expanded_src);
    279 
    280    check_expanded_source(type, expanded_src);
    281    check_instructions(&instructions, type, deref);
    282 }
    283 
    284 TEST_F(expand_source, uint64_expression)
    285 {
    286    const glsl_type *const type = glsl_type::uint64_t_type;
    287    ir_expression *const expr = create_expression(mem_ctx, type);
    288 
    289    lower_64bit::expand_source(*body, expr, expanded_src);
    290 
    291    check_expanded_source(type, expanded_src);
    292    check_instructions(&instructions, type, expr);
    293 }
    294 
    295 TEST_F(expand_source, u64vec2_expression)
    296 {
    297    const glsl_type *const type = glsl_type::u64vec2_type;
    298    ir_expression *const expr = create_expression(mem_ctx, type);
    299 
    300    lower_64bit::expand_source(*body, expr, expanded_src);
    301 
    302    check_expanded_source(type, expanded_src);
    303    check_instructions(&instructions, type, expr);
    304 }
    305 
    306 TEST_F(expand_source, u64vec3_expression)
    307 {
    308    const glsl_type *const type = glsl_type::u64vec3_type;
    309    ir_expression *const expr = create_expression(mem_ctx, type);
    310 
    311    lower_64bit::expand_source(*body, expr, expanded_src);
    312 
    313    check_expanded_source(type, expanded_src);
    314    check_instructions(&instructions, type, expr);
    315 }
    316 
    317 TEST_F(expand_source, u64vec4_expression)
    318 {
    319    const glsl_type *const type = glsl_type::u64vec4_type;
    320    ir_expression *const expr = create_expression(mem_ctx, type);
    321 
    322    lower_64bit::expand_source(*body, expr, expanded_src);
    323 
    324    check_expanded_source(type, expanded_src);
    325    check_instructions(&instructions, type, expr);
    326 }
    327 
    328 TEST_F(expand_source, int64_expression)
    329 {
    330    const glsl_type *const type = glsl_type::int64_t_type;
    331    ir_expression *const expr = create_expression(mem_ctx, type);
    332 
    333    lower_64bit::expand_source(*body, expr, expanded_src);
    334 
    335    check_expanded_source(type, expanded_src);
    336    check_instructions(&instructions, type, expr);
    337 }
    338 
    339 TEST_F(expand_source, i64vec2_expression)
    340 {
    341    const glsl_type *const type = glsl_type::i64vec2_type;
    342    ir_expression *const expr = create_expression(mem_ctx, type);
    343 
    344    lower_64bit::expand_source(*body, expr, expanded_src);
    345 
    346    check_expanded_source(type, expanded_src);
    347    check_instructions(&instructions, type, expr);
    348 }
    349 
    350 TEST_F(expand_source, i64vec3_expression)
    351 {
    352    const glsl_type *const type = glsl_type::i64vec3_type;
    353    ir_expression *const expr = create_expression(mem_ctx, type);
    354 
    355    lower_64bit::expand_source(*body, expr, expanded_src);
    356 
    357    check_expanded_source(type, expanded_src);
    358    check_instructions(&instructions, type, expr);
    359 }
    360 
    361 TEST_F(expand_source, i64vec4_expression)
    362 {
    363    const glsl_type *const type = glsl_type::i64vec4_type;
    364    ir_expression *const expr = create_expression(mem_ctx, type);
    365 
    366    lower_64bit::expand_source(*body, expr, expanded_src);
    367 
    368    check_expanded_source(type, expanded_src);
    369    check_instructions(&instructions, type, expr);
    370 }
    371 
    372 class compact_destination : public ::testing::Test {
    373 public:
    374    virtual void SetUp();
    375    virtual void TearDown();
    376 
    377    exec_list instructions;
    378    ir_factory *body;
    379    ir_variable *expanded_src[4];
    380    void *mem_ctx;
    381 };
    382 
    383 void
    384 compact_destination::SetUp()
    385 {
    386    mem_ctx = ralloc_context(NULL);
    387 
    388    memset(expanded_src, 0, sizeof(expanded_src));
    389    instructions.make_empty();
    390    body = new ir_factory(&instructions, mem_ctx);
    391 }
    392 
    393 void
    394 compact_destination::TearDown()
    395 {
    396    delete body;
    397    body = NULL;
    398 
    399    ralloc_free(mem_ctx);
    400    mem_ctx = NULL;
    401 }
    402 
    403 TEST_F(compact_destination, uint64)
    404 {
    405    const glsl_type *const type = glsl_type::uint64_t_type;
    406 
    407    for (unsigned i = 0; i < type->vector_elements; i++) {
    408       expanded_src[i] = new(mem_ctx) ir_variable(glsl_type::uvec2_type,
    409                                                  "result",
    410                                                  ir_var_temporary);
    411    }
    412 
    413    ir_dereference_variable *deref =
    414       lower_64bit::compact_destination(*body,
    415                                        type,
    416                                        expanded_src);
    417 
    418    ASSERT_EQ(ir_type_dereference_variable, deref->ir_type);
    419    EXPECT_EQ(type, deref->var->type) <<
    420       "    Got " <<
    421       deref->var->type->name <<
    422       ", expected " <<
    423       type->name;
    424 
    425    ir_instruction *ir;
    426 
    427    ASSERT_FALSE(instructions.is_empty());
    428    ir = (ir_instruction *) instructions.pop_head();
    429    ir_variable *const var = ir->as_variable();
    430    ASSERT_NE((void *)0, var);
    431    EXPECT_EQ(deref->var, var);
    432 
    433    for (unsigned i = 0; i < type->vector_elements; i++) {
    434       ASSERT_FALSE(instructions.is_empty());
    435       ir = (ir_instruction *) instructions.pop_head();
    436       ir_assignment *const assign = ir->as_assignment();
    437       ASSERT_NE((void *)0, assign);
    438       EXPECT_EQ(deref->var, assign->lhs->variable_referenced());
    439    }
    440 }
    441