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