Home | History | Annotate | Download | only in tests
      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
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 #include <gtest/gtest.h>
     24 #include "ir.h"
     25 #include "ir_builder.h"
     26 #include "opt_add_neg_to_sub.h"
     27 
     28 using namespace ir_builder;
     29 
     30 class add_neg_to_sub : public ::testing::Test {
     31 public:
     32    virtual void SetUp();
     33    virtual void TearDown();
     34 
     35    exec_list instructions;
     36    ir_factory *body;
     37    void *mem_ctx;
     38    ir_variable *var_a;
     39    ir_variable *var_b;
     40    ir_variable *var_c;
     41    add_neg_to_sub_visitor v;
     42 };
     43 
     44 void
     45 add_neg_to_sub::SetUp()
     46 {
     47    mem_ctx = ralloc_context(NULL);
     48 
     49    instructions.make_empty();
     50    body = new ir_factory(&instructions, mem_ctx);
     51 
     52    var_a = new(mem_ctx) ir_variable(glsl_type::float_type,
     53                                     "a",
     54                                     ir_var_temporary);
     55 
     56    var_b = new(mem_ctx) ir_variable(glsl_type::float_type,
     57                                     "b",
     58                                     ir_var_temporary);
     59 
     60    var_c = new(mem_ctx) ir_variable(glsl_type::float_type,
     61                                     "c",
     62                                     ir_var_temporary);
     63 }
     64 
     65 void
     66 add_neg_to_sub::TearDown()
     67 {
     68    delete body;
     69    body = NULL;
     70 
     71    ralloc_free(mem_ctx);
     72    mem_ctx = NULL;
     73 }
     74 
     75 TEST_F(add_neg_to_sub, a_plus_b)
     76 {
     77    body->emit(assign(var_c, add(var_a, var_b)));
     78 
     79    visit_list_elements(&v, &instructions);
     80 
     81    ASSERT_FALSE(instructions.is_empty());
     82 
     83    ir_instruction *const ir = (ir_instruction *) instructions.pop_head();
     84 
     85    EXPECT_TRUE(instructions.is_empty());
     86 
     87    /* The resulting instruction should be 'c = a + b'. */
     88    ir_assignment *const assign = ir->as_assignment();
     89    ASSERT_NE((void *)0, assign);
     90 
     91    EXPECT_EQ(var_c, assign->lhs->variable_referenced());
     92 
     93    ir_expression *const expr = assign->rhs->as_expression();
     94    ASSERT_NE((void *)0, expr);
     95    EXPECT_EQ(ir_binop_add, expr->operation);
     96 
     97    ir_dereference_variable *const deref_a =
     98       expr->operands[0]->as_dereference_variable();
     99    ir_dereference_variable *const deref_b =
    100       expr->operands[1]->as_dereference_variable();
    101 
    102    ASSERT_NE((void *)0, deref_a);
    103    EXPECT_EQ(var_a, deref_a->var);
    104    ASSERT_NE((void *)0, deref_b);
    105    EXPECT_EQ(var_b, deref_b->var);
    106 }
    107 
    108 TEST_F(add_neg_to_sub, a_plus_neg_b)
    109 {
    110    body->emit(assign(var_c, add(var_a, neg(var_b))));
    111 
    112    visit_list_elements(&v, &instructions);
    113 
    114    ASSERT_FALSE(instructions.is_empty());
    115 
    116    ir_instruction *const ir = (ir_instruction *) instructions.pop_head();
    117 
    118    EXPECT_TRUE(instructions.is_empty());
    119 
    120    /* The resulting instruction should be 'c = a - b'. */
    121    ir_assignment *const assign = ir->as_assignment();
    122    ASSERT_NE((void *)0, assign);
    123 
    124    EXPECT_EQ(var_c, assign->lhs->variable_referenced());
    125 
    126    ir_expression *const expr = assign->rhs->as_expression();
    127    ASSERT_NE((void *)0, expr);
    128    EXPECT_EQ(ir_binop_sub, expr->operation);
    129 
    130    ir_dereference_variable *const deref_a =
    131       expr->operands[0]->as_dereference_variable();
    132    ir_dereference_variable *const deref_b =
    133       expr->operands[1]->as_dereference_variable();
    134 
    135    ASSERT_NE((void *)0, deref_a);
    136    EXPECT_EQ(var_a, deref_a->var);
    137    ASSERT_NE((void *)0, deref_b);
    138    EXPECT_EQ(var_b, deref_b->var);
    139 }
    140 
    141 TEST_F(add_neg_to_sub, neg_a_plus_b)
    142 {
    143    body->emit(assign(var_c, add(neg(var_a), var_b)));
    144 
    145    visit_list_elements(&v, &instructions);
    146 
    147    ASSERT_FALSE(instructions.is_empty());
    148 
    149    ir_instruction *const ir = (ir_instruction *) instructions.pop_head();
    150 
    151    EXPECT_TRUE(instructions.is_empty());
    152 
    153    /* The resulting instruction should be 'c = b - a'. */
    154    ir_assignment *const assign = ir->as_assignment();
    155    ASSERT_NE((void *)0, assign);
    156 
    157    EXPECT_EQ(var_c, assign->lhs->variable_referenced());
    158 
    159    ir_expression *const expr = assign->rhs->as_expression();
    160    ASSERT_NE((void *)0, expr);
    161    EXPECT_EQ(ir_binop_sub, expr->operation);
    162 
    163    ir_dereference_variable *const deref_b =
    164       expr->operands[0]->as_dereference_variable();
    165    ir_dereference_variable *const deref_a =
    166       expr->operands[1]->as_dereference_variable();
    167 
    168    ASSERT_NE((void *)0, deref_a);
    169    EXPECT_EQ(var_a, deref_a->var);
    170    ASSERT_NE((void *)0, deref_b);
    171    EXPECT_EQ(var_b, deref_b->var);
    172 }
    173 
    174 TEST_F(add_neg_to_sub, neg_a_plus_neg_b)
    175 {
    176    body->emit(assign(var_c, add(neg(var_a), neg(var_b))));
    177 
    178    visit_list_elements(&v, &instructions);
    179 
    180    ASSERT_FALSE(instructions.is_empty());
    181 
    182    ir_instruction *const ir = (ir_instruction *) instructions.pop_head();
    183 
    184    EXPECT_TRUE(instructions.is_empty());
    185 
    186    /* The resulting instruction should be 'c = -b - a'. */
    187    ir_assignment *const assign = ir->as_assignment();
    188    ASSERT_NE((void *)0, assign);
    189 
    190    EXPECT_EQ(var_c, assign->lhs->variable_referenced());
    191 
    192    ir_expression *const expr = assign->rhs->as_expression();
    193    ASSERT_NE((void *)0, expr);
    194    EXPECT_EQ(ir_binop_sub, expr->operation);
    195 
    196    ir_expression *const neg_b = expr->operands[0]->as_expression();
    197    ir_dereference_variable *const deref_a =
    198       expr->operands[1]->as_dereference_variable();
    199 
    200    ASSERT_NE((void *)0, deref_a);
    201    EXPECT_EQ(var_a, deref_a->var);
    202 
    203    ASSERT_NE((void *)0, neg_b);
    204 
    205    ir_dereference_variable *const deref_b =
    206       neg_b->operands[0]->as_dereference_variable();
    207 
    208    ASSERT_NE((void *)0, deref_b);
    209    EXPECT_EQ(var_b, deref_b->var);
    210 }
    211