1/* 2 * Copyright © 2010 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 24/** 25 * \file lower_vec_index_to_swizzle.cpp 26 * 27 * Turns constant indexing into vector types to swizzles. This will 28 * let other swizzle-aware optimization passes catch these constructs, 29 * and codegen backends not have to worry about this case. 30 */ 31 32#include "ir.h" 33#include "ir_visitor.h" 34#include "ir_optimization.h" 35#include "glsl_types.h" 36 37/** 38 * Visitor class for replacing expressions with ir_constant values. 39 */ 40 41class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor { 42public: 43 ir_vec_index_to_swizzle_visitor() 44 { 45 progress = false; 46 } 47 48 ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val); 49 50 virtual ir_visitor_status visit_enter(ir_expression *); 51 virtual ir_visitor_status visit_enter(ir_swizzle *); 52 virtual ir_visitor_status visit_enter(ir_assignment *); 53 virtual ir_visitor_status visit_enter(ir_return *); 54 virtual ir_visitor_status visit_enter(ir_call *); 55 virtual ir_visitor_status visit_enter(ir_if *); 56 57 bool progress; 58}; 59 60ir_rvalue * 61ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir) 62{ 63 ir_dereference_array *deref = ir->as_dereference_array(); 64 ir_constant *ir_constant; 65 66 if (!deref) 67 return ir; 68 69 if (deref->array->type->is_matrix() || deref->array->type->is_array()) 70 return ir; 71 72 assert(deref->array_index->type->base_type == GLSL_TYPE_INT); 73 ir_constant = deref->array_index->constant_expression_value(); 74 if (!ir_constant) 75 return ir; 76 77 void *ctx = hieralloc_parent(ir); 78 this->progress = true; 79 return new(ctx) ir_swizzle(deref->array, 80 ir_constant->value.i[0], 0, 0, 0, 1); 81} 82 83ir_visitor_status 84ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir) 85{ 86 unsigned int i; 87 88 for (i = 0; i < ir->get_num_operands(); i++) { 89 ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]); 90 } 91 92 return visit_continue; 93} 94 95ir_visitor_status 96ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir) 97{ 98 /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which 99 * the result of indexing a vector is. But maybe at some point we'll end up 100 * using swizzling of scalars for vector construction. 101 */ 102 ir->val = convert_vec_index_to_swizzle(ir->val); 103 104 return visit_continue; 105} 106 107ir_visitor_status 108ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir) 109{ 110 ir->set_lhs(convert_vec_index_to_swizzle(ir->lhs)); 111 ir->rhs = convert_vec_index_to_swizzle(ir->rhs); 112 113 return visit_continue; 114} 115 116ir_visitor_status 117ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir) 118{ 119 foreach_iter(exec_list_iterator, iter, *ir) { 120 ir_rvalue *param = (ir_rvalue *)iter.get(); 121 ir_rvalue *new_param = convert_vec_index_to_swizzle(param); 122 123 if (new_param != param) { 124 param->replace_with(new_param); 125 } 126 } 127 128 return visit_continue; 129} 130 131ir_visitor_status 132ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir) 133{ 134 if (ir->value) { 135 ir->value = convert_vec_index_to_swizzle(ir->value); 136 } 137 138 return visit_continue; 139} 140 141ir_visitor_status 142ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir) 143{ 144 ir->condition = convert_vec_index_to_swizzle(ir->condition); 145 146 return visit_continue; 147} 148 149bool 150do_vec_index_to_swizzle(exec_list *instructions) 151{ 152 ir_vec_index_to_swizzle_visitor v; 153 154 v.run(instructions); 155 156 return v.progress; 157} 158