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