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