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 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
TearDown()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
TEST_F(add_neg_to_sub,a_plus_b)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
TEST_F(add_neg_to_sub,a_plus_neg_b)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
TEST_F(add_neg_to_sub,neg_a_plus_b)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
TEST_F(add_neg_to_sub,neg_a_plus_neg_b)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